README.md
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