class CompareAndSwapRegister: "CompareAndSwap class" def __init__(self): self.value = 0 def CompareAndSwap(self, oldval, newval): presval = self.value if (presval == oldval): self.value = newval return presval def __str__(self): return str(self.value)
import re def lineCAS(reg, line): pat = re.compile('\s*(\d+)\s+(\d+)\s*') mat = pat.match(line) if (mat == None): return 'Bad Syntax' else: return (str(reg.CompareAndSwap(int(mat.group(1)), int(mat.group(2)))))
#! /usr/bin/python from CompareAndSwap import CompareAndSwapRegister from lineCAS import lineCAS def stdinCAS(): x = CompareAndSwapRegister() try: while True: line = raw_input() print lineCAS(x, line) except EOFError: pass if __name__ == "__main__": stdinCAS()
#! /usr/bin/python from CompareAndSwap import CompareAndSwapRegister import re def stdinCAS(): pat = re.compile('\s*(\d+)\s+(\d+)\s*') reg = CompareAndSwapRegister() try: while True: line = raw_input() mat = pat.match(line) if (mat == None): print 'Bad Syntax' else: print (str(reg.CompareAndSwap(int(mat.group(1)), int(mat.group(2))))) except EOFError: pass if __name__ == "__main__": stdinCAS()
#! /usr/bin/python from CompareAndSwap import CompareAndSwapRegister import re import socket def serverCAS(): pat = re.compile('^\s*(\d+)\s+(\d+)\s*\n$') reg = CompareAndSwapRegister() s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) try: s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) ; s.bind(('', 22222)) s.listen(1) while True: strm, addr = s.accept() print "Connection from ", addr line = strm.recv(1000) while line: print line, mat = pat.match(line) if (mat == None): repl = 'Bad Syntax' else: repl = (str(reg.CompareAndSwap(int(mat.group(1)), int(mat.group(2))))) strm.send(repl+'\n\r') line = strm.recv(1000) strm.close() except KeyboardInterrupt: print 'Exiting' s.close() if __name__ == "__main__": serverCAS()
#! /usr/bin/python import socket import sys if len(sys.argv) == 4: s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.connect((sys.argv[1], 22222)) s.send(sys.argv[2] + ' ' + sys.argv[3] + '\n') resp = s.recv(1000) print resp, s.close()
Try sending incomplete lines and multiple lines.
#! /usr/bin/python import socket import sys if len(sys.argv) == 3: s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.connect((sys.argv[1], 22222)) s.send(sys.argv[2]) resp = s.recv(1000) print resp, s.close()
Break up the line. This should result in unpredictable output.
#! /usr/bin/python import socket import sys if len(sys.argv) == 4: s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.connect((sys.argv[1], 22222)) s.send(sys.argv[2]) s.send(' ') s.send(sys.argv[3]) s.send('\n') resp = s.recv(1000) print resp, s.close()
Because TCP is stream oriented, there is a problem in reading line oriented input.
recv
until it doesSocket
Socket makefile
methodfile
object
readline
write
flush
close
The server can only process one connection at a time.
Try out the following Python program.
import os pid = os.fork() print 'PID = ', pid print 'Hello world'
In the original Unix solution to this problem, which works well if the two connections are independent and requires shared memory if they don't, the following calls are used to create independent processes. This will be illustrated on the board.
fork
dup
close
exit
wait
shmxxx
for share memoryFortunately, much of the hard work can be put off to a super server. For CGI scripts, the web server acts as a super server. RPC mechanisms also resemble super servers.
The bad solution is to use non-blocking socket and write busy-wait loops to test them.
The hard one-process solution is to use a blocking call that can wait
on several input sources simultaneously.
This one uses the poll
system call
with can be used via the
Python select
module.
Here's the basic idea.
select
to wait for I/O
accept
to create a new communicating socketsend
calls sends the entire buffer
And here's some examples.
The preferred modern solution is to use
threads with
Python's
threading
module.
threading.Thread
with keyword arugments
t = threading.Thread(target=HandleConnection, args=(reg,strm,addr,))
t.start()
Finally, due to the use of a Global Interpreter Lock (GIL) in the CPython and Ruby MRI interpreters, think hard before using threads for compute-bound computation in Python and Ruby.