|
Python/FAQ/Сокеты
Материал из Wiki.crossplatform.ru
[править] 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@@
|