Python/FAQ/Сокеты
Материал из Wiki.crossplatform.ru
Версия от 14:28, 3 декабря 2008; Root (Обсуждение | вклад)
· Python · |
[править] Introduction
# Socket Programming (tcp/ip and udp/ip) import socket # Convert human readable form to 32 bit value packed_ip = socket.inet_aton("208.146.240.1") packed_ip = socket.inet_aton("www.oreilly.com") # Convert 32 bit value to ip adress ip_adress = socket.inet_ntoa(packed_ip) # Create socket object socketobj = socket(family, type) # Example socket.AF_INT, socket.SOCK_STREAM # Get socketname socketobj.getsockname() # Example, get port adress of client
[править] Writing a TCP Client
# Example: Connect to a server (tcp) # Connect to a smtp server at localhost and send an email. # For real applications you should use smtplib. import socket s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.connect(("localhost", 25)) # SMTP print s.recv(1024) s.send("mail from: <pleac@localhost>\n") print s.recv(1024) s.send("rcpt to: <guettli@localhost>\n") print s.recv(1024) s.send("data\n") print s.recv(1024) s.send("From: Python Lover\nSubject: Python is better then perl\n\nYES!\n.\n") print s.recv(1024) s.close()
[править] Writing a TCP Server
# Create a Server, calling handler for every client # You can test it with "telnet localhost 1029" from SocketServer import TCPServer from SocketServer import BaseRequestHandler class MyHandler(BaseRequestHandler): def handle(self): print "I got an request" server = TCPServer(("127.0.0.1", 1029), MyHandler) server.serve_forever()
[править] Communicating over TCP
# This is the continuation of 17.2 import time from SocketServer import TCPServer from SocketServer import BaseRequestHandler class MyHandler(BaseRequestHandler): def handle(self): # self.request is the socket object print "%s I got an request from ip=%s port=%s" % ( time.strftime("%Y-%m-%d %H:%M:%S"), self.client_address[0], self.client_address[1] ) self.request.send("What is your name?\n") bufsize=1024 response=self.request.recv(bufsize).strip() # or recv(bufsize, flags) data_to_send="Welcome %s!\n" % response self.request.send(data_to_send) # or send(data, flags) print "%s connection finnished" % self.client_address[0] server = TCPServer(("127.0.0.1", 1028), MyHandler) server.serve_forever() # ----------------- # Using select import select import socket in_list = [] in_list.append(mysocket) in_list.append(myfile) # ... out_list = [] out_list.append(...) except_list = [] except_list.append(...) (in_, out_, exc_) = select.select(in_list, out_list, except_list, timeout) for fd in in_: print "Can read", fd for fd in out_: print "Can write", fd for fd in exc_: print "Exception on", fd # Missing: setting TCP_NODELAY
[править] Setting Up a UDP Client
import socket # Set up a UDP socket s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) # send MSG = 'Hello' HOSTNAME = '127.0.0.1' PORTNO = 10000 s.connect((HOSTNAME, PORTNO)) if len(MSG) != s.send(MSG): # where to get error message "$!". print "cannot send to %s(%d):" % (HOSTNAME,PORTNO) raise SystemExit(1) MAXLEN = 1024 (data,addr) = s.recvfrom(MAXLEN) s.close() print '%s(%d) said "%s"' % (addr[0],addr[1], data) # download the following standalone program #!/usr/bin/python # clockdrift - compare another system's clock with this one import socket import struct import sys import time if len(sys.argv)>1: him = sys.argv[1] else: him = '127.1' SECS_of_70_YEARS = 2208988800 s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) s.connect((him,socket.getservbyname('time','udp'))) s.send('') (ptime, src) = s.recvfrom(4) host = socket.gethostbyaddr(src[0]) delta = struct.unpack("!L", ptime)[0] - SECS_of_70_YEARS - time.time() print "Clock on %s is %d seconds ahead of this one." % (host[0], delta)
[править] Setting Up a UDP Server
import socket import sys s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) try: s.bind(('', server_port)) except socket.error, err: print "Couldn't be a udp server on port %d : %s" % ( server_port, err) raise SystemExit while True: datagram = s.recv(MAX_TO_READ) if not datagram: break # do something s.close() # or import SocketServer class handler(SocketServer.DatagramRequestHandler): def handle(self): # do something (with self.request[0]) s = SocketServer.UDPServer(('',10000), handler) s.serve_forever() # download the following standalone program #!/usr/bin/python # udpqotd - UDP message server import SocketServer PORTNO = 5151 class handler(SocketServer.DatagramRequestHandler): def handle(self): newmsg = self.rfile.readline().rstrip() print "Client %s said ``%s''" % (self.client_address[0], newmsg) self.wfile.write(self.server.oldmsg) self.server.oldmsg = newmsg s = SocketServer.UDPServer(('',PORTNO), handler) print "Awaiting UDP messages on port %d" % PORTNO s.oldmsg = "This is the starting message." s.serve_forever() # download the following standalone program #!/usr/bin/python # udpmsg - send a message to the udpquotd server import socket import sys MAXLEN = 1024 PORTNO = 5151 TIMEOUT = 5 server_host = sys.argv[1] msg = " ".join(sys.argv[2:]) sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) sock.settimeout(TIMEOUT) sock.connect((server_host, PORTNO)) sock.send(msg) try: msg = sock.recv(MAXLEN) ipaddr, port = sock.getpeername() hishost = socket.gethostbyaddr(ipaddr) print "Server %s responded ``%s''" % ( hishost[0], msg) except: print "recv from %s failed (timeout or no server running)." % ( server_host ) sock.close()
[править] Using UNIX Domain Sockets
import socket import os, os.path if os.path.exists("/tmp/mysock"): os.remove("/tmp/mysock") server = socket.socket(socket.AF_UNIX, socket.SOCK_DGRAM) server.bind("/tmp/mysock") client = socket.socket(socket.AF_UNIX, socket.SOCK_DGRAM) client.connect("/tmp/mysock")
[править] Identifying the Other End of a Socket
ipaddr, port = s.getpeername() hostname, aliaslist, ipaddrlist = socket.gethostbyaddr(ipaddr) ipaddr = socket.gethostbyname('www.python.org') # '194.109.137.226' hostname, aliaslist, ipaddrlist = socket.gethostbyname_ex('www.python.org') # ('fang.python.org', ['www.python.org'], ['194.109.137.226']) socket.gethostbyname_ex('www.google.org') # ('www.l.google.com', ['www.google.org', 'www.google.com'], # ['64.233.161.147','64.233.161.104', '64.233.161.99'])
[править] Finding Your Own Name and Address
import os kernel, hostname, release, version, hardware = os.uname() import socket address = socket.gethostbyname(hostname) hostname = socket.gethostbyaddr(address) hostname, aliaslist, ipaddrlist = socket.gethostbyname_ex(hostname) # e.g. ('lx3.local', ['lx3', 'b70'], ['192.168.0.13', '192.168.0.70'])
[править] Closing a Socket After Forking
socket.shutdown(0) # Further receives are disallowed socket.shutdown(1) # Further sends are disallowed. socket.shutdown(2) # Further sends and receives are disallowed. # server.send("my request\n") # send some data server.shutdown(1) # send eof; no more writing answer = server.recv(1000) # but you can still read
[править] Writing Bidirectional Clients
# @@INCOMPLETE@@ # @@INCOMPLETE@@
[править] Forking Servers
# @@INCOMPLETE@@ # @@INCOMPLETE@@
[править] Pre-Forking Servers
# @@INCOMPLETE@@ # @@INCOMPLETE@@
[править] Non-Forking Servers
# @@INCOMPLETE@@ # @@INCOMPLETE@@
[править] Writing a Multi-Homed Server
# @@INCOMPLETE@@ # @@INCOMPLETE@@
[править] Making a Daemon Server
# @@INCOMPLETE@@ # @@INCOMPLETE@@
[править] Restarting a Server on Demand
#------------------------------ # Restart programm on signal SIGHUP # Script must be executable: chmod a+x foo.py #!/usr/bin/env python import os import sys import time import signal def phoenix(signum, frame): print "Restarting myself: %s %s" % (self, args) os.execv(self, args) self = os.path.abspath(sys.argv[0]) args = sys.argv[:] signal.signal(signal.SIGHUP, phoenix) while True: print "work" time.sleep(1) #-------------------- # Read config file on SIGHUP import signal config_file = "/usr/local/etc/myprog/server_conf.py" def read_config(): execfile(config_file) signal.signal(signal.SIGHUP, read_config)
[править] Program: backsniff
# chroot import os try: os.chroot("/var/daemon") except Exception: print "Could not chroot" raise SystemExit(1) #----------------------------- # fork (Unix): Create a new process # if pid == 0 --> parent process # else child process import os pid = os.fork() if pid: print "I am the new child %s" % pid raise SystemExit else: print "I am still the parent" # ---------------------------- # setsid (Unix): Create a new session import os id=os.setsid() # ---------------------------- # Work until INT TERM or HUP signal is received import time import signal time_to_die = 0 def sighandler(signum, frame): print "time to die" global time_to_die time_to_die = 1 signal.signal(signal.SIGINT, sighandler) signal.signal(signal.SIGTERM, sighandler) signal.signal(signal.SIGHUP, sighandler) while not time_to_die: print "work" time.sleep(1)
[править] Program: fwdport
# @@INCOMPLETE@@ # @@INCOMPLETE@@