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&#64;localhost>\n")
print s.recv(1024)
s.send("rcpt to: <guettli&#64;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@@