1# Building of samples for different platforms 2 3# Requirements 4- NET Core Standard 3.1 (LTS) runtime or SDK (see below for further info) 5 6# How to build 7- Download and install the latest .NET Core SDK for your platform https://dotnet.microsoft.com/download/dotnet-core 8- Ensure that you have thrift.exe which supports netstd lib and it added to PATH 9- Go to current folder 10- Run **build.sh** or **build.cmd** from the root of cloned repository 11- Check tests in **src/Tests** folder 12- Continue with /tutorials/netstd 13 14# How to run 15 16Depending on the platform, the name of the generated executables will vary. On Linux, it is just "Client" or "Server", on Windows it is "Client.exe" and "Server.exe". In the following, we use the abbreviated form "Client" and "Server". 17 18- build 19- go to folder (Client/Server) 20- run the generated executables: server first, then client from a second console 21 22# Known issues 23- In trace logging mode you can see some not important internal exceptions 24 25# Running of samples 26On machines that do not have the SDK installed, you need to install the NET Core runtime first. The SDK is only needed to build programs, otherwise the runtime is sufficient. 27 28# NetCore Server 29 30Usage: 31 32 Server -help 33 will diplay help information 34 35 Server -tr:<transport> -pr:<protocol> 36 will run server with specified arguments (tcp transport and binary protocol by default) 37 38Options: 39 40 -tr (transport): 41 tcp - (default) tcp transport will be used (host - ""localhost"", port - 9090) 42 namedpipe - namedpipe transport will be used (pipe address - "".test"") 43 http - http transport will be used (http address - ""localhost:9090"") 44 tcptls - tcp transport with tls will be used (host - ""localhost"", port - 9090) 45 46 -bf (buffering): 47 none - (default) no transport factory will be used 48 buffered - buffered transport factory will be used 49 framed - framed transport factory will be used (this must match the client) 50 51 -pr (protocol): 52 binary - (default) binary protocol will be used 53 compact - compact protocol will be used 54 json - json protocol will be used 55 multiplexed - multiplexed protocol will be used 56 57Sample: 58 59 Server -tr:tcp 60 61**Remarks**: 62 63 For TcpTls mode certificate's file ThriftTest.pfx should be in directory with binaries in case of command line usage (or at project level in case of debugging from IDE). 64 Password for certificate - "ThriftTest". 65 66 67 68# NetCore Client 69 70Usage: 71 72 Client -help 73 will diplay help information 74 75 Client -tr:<transport> -pr:<protocol> -mc:<numClients> 76 will run client with specified arguments (tcp transport and binary protocol by default) 77 78Options: 79 80 -tr (transport): 81 tcp - (default) tcp transport will be used (host - ""localhost"", port - 9090) 82 namedpipe - namedpipe transport will be used (pipe address - "".test"") 83 http - http transport will be used (address - ""http://localhost:9090"") 84 tcptls - tcp tls transport will be used (host - ""localhost"", port - 9090) 85 86 -bf (buffering): 87 none - (default) no transport factory will be used 88 buffered - buffered transport factory will be used 89 framed - framed transport factory will be used (this must match the client) 90 91 -pr (protocol): 92 binary - (default) binary protocol will be used 93 compact - compact protocol will be used 94 json - json protocol will be used 95 multiplexed - multiplexed protocol will be used 96 97 -mc (multiple clients): 98 <numClients> - number of multiple clients to connect to server (max 100, default 1) 99 100Sample: 101 102 Client -tr:tcp -pr:binary -mc:10 103 104Remarks: 105 106 For TcpTls mode certificate's file ThriftTest.pfx should be in directory 107 with binaries in case of command line usage (or at project level in case of debugging from IDE). 108 Password for certificate - "ThriftTest". 109 110# How to test communication between NetCore and Python 111 112* Generate code with the latest **thrift** utility 113* Ensure that **thrift** generated folder **gen-py** with generated code for Python exists 114* Create **client.py** and **server.py** from the code examples below and save them to the folder with previosly generated folder **gen-py** 115* Run netstd samples (client and server) and python samples (client and server) 116 117Remarks: 118 119Samples of client and server code below use correct methods (operations) 120and fields (properties) according to generated contracts from *.thrift files 121 122At Windows 10 add record **127.0.0.1 testserver** to **C:\Windows\System32\drivers\etc\hosts** file 123for correct work of python server 124 125 126**Python Client:** 127 128```python 129import sys 130import glob 131sys.path.append('gen-py') 132 133from tutorial import Calculator 134from tutorial.ttypes import InvalidOperation, Operation, Work 135 136from thrift import Thrift 137from thrift.transport import TSocket 138from thrift.transport import TTransport 139from thrift.protocol import TBinaryProtocol 140 141 142def main(): 143 # Make socket 144 transport = TSocket.TSocket('127.0.0.1', 9090) 145 146 # Buffering is critical. Raw sockets are very slow 147 transport = TTransport.TBufferedTransport(transport) 148 149 # Wrap in a protocol 150 protocol = TBinaryProtocol.TBinaryProtocol(transport) 151 152 # Create a client to use the protocol encoder 153 client = Calculator.Client(protocol) 154 155 # Connect! 156 transport.open() 157 158 client.Ping() 159 print('ping()') 160 161 sum = client.Add(1, 1) 162 print(('1+1=%d' % (sum))) 163 164 work = Work() 165 166 work.Op = Operation.Divide 167 work.Num1 = 1 168 work.Num2 = 0 169 170 try: 171 quotient = client.Calculate(1, work) 172 print('Whoa? You know how to divide by zero?') 173 print('FYI the answer is %d' % quotient) 174 except InvalidOperation as e: 175 print(('InvalidOperation: %r' % e)) 176 177 work.Op = Operation.Substract 178 work.Num1 = 15 179 work.Num2 = 10 180 181 diff = client.Calculate(1, work) 182 print(('15-10=%d' % (diff))) 183 184 log = client.GetStruct(1) 185 print(('Check log: %s' % (log.Value))) 186 187 client.Zip() 188 print('zip()') 189 190 # Close! 191 transport.close() 192 193if __name__ == '__main__': 194 try: 195 main() 196 except Thrift.TException as tx: 197 print('%s' % tx.message) 198``` 199 200 201**Python Server:** 202 203 204```python 205import glob 206import sys 207sys.path.append('gen-py') 208 209from tutorial import Calculator 210from tutorial.ttypes import InvalidOperation, Operation 211 212from shared.ttypes import SharedStruct 213 214from thrift.transport import TSocket 215from thrift.transport import TTransport 216from thrift.protocol import TBinaryProtocol 217from thrift.server import TServer 218 219 220class CalculatorHandler: 221 def __init__(self): 222 self.log = {} 223 224 def Ping(self): 225 print('ping()') 226 227 def Add(self, n1, n2): 228 print('add(%d,%d)' % (n1, n2)) 229 return n1 + n2 230 231 def Calculate(self, logid, work): 232 print('calculate(%d, %r)' % (logid, work)) 233 234 if work.Op == Operation.Add: 235 val = work.Num1 + work.Num2 236 elif work.Op == Operation.Substract: 237 val = work.Num1 - work.Num2 238 elif work.Op == Operation.Multiply: 239 val = work.Num1 * work.Num2 240 elif work.Op == Operation.Divide: 241 if work.Num2 == 0: 242 raise InvalidOperation(work.Op, 'Cannot divide by 0') 243 val = work.Num1 / work.Num2 244 else: 245 raise InvalidOperation(work.Op, 'Invalid operation') 246 247 log = SharedStruct() 248 log.Key = logid 249 log.Value = '%d' % (val) 250 self.log[logid] = log 251 252 return val 253 254 def GetStruct(self, key): 255 print('getStruct(%d)' % (key)) 256 return self.log[key] 257 258 def Zip(self): 259 print('zip()') 260 261if __name__ == '__main__': 262 handler = CalculatorHandler() 263 processor = Calculator.Processor(handler) 264 transport = TSocket.TServerSocket(host="testserver", port=9090) 265 tfactory = TTransport.TBufferedTransportFactory() 266 pfactory = TBinaryProtocol.TBinaryProtocolFactory() 267 268 server = TServer.TSimpleServer(processor, transport, tfactory, pfactory) 269 print('Starting the server...') 270 server.serve() 271 print('done.') 272 273 # You could do one of these for a multithreaded server 274 # server = TServer.TThreadedServer(processor, transport, tfactory, pfactory) 275 # server = TServer.TThreadPoolServer(processor, transport, tfactory, pfactory) 276``` 277