python socket 编程简单入门

想讲讲套接字的概念

套接字,即英文socket的中文意译,起源于20世纪70年代,是加利福利亚大学的伯克利版本UNIX(称为BSD UNIX)的一部分。目的是实现主机上运行的一个程序与另一个运行的程序进行通信。

套接字像一个电话插孔--允许通信的一些基础设施,那么主机号和端口号就像区号和电话号码的组合。

 

套接字类型

1 UNIX套接字

即AF_UNIX, 它代表地址家族:UNIX。Python在内的大多数受欢迎的平台都使用缩写AF指代。

2 网络套接字

即AF_INET,它代表地址家族:因特网。而AF_INET6用于IPV6

3 其他套接字

AF_NETLINK家族,AF_TIPC ,这两种是特殊的LINUX套接字类型

 

python支持以上四种套接字

 

实际使用中,我们用的最多的时AF_INET,其有可以分为:

1 面向连接的套接字 

即实现TCP协议的套接字,具体名称为SOCK_STREAM

2 无连接的套接字

即实现UDP协议的套接字,名称为SOCK_DGRAM(datagram数据报)

 

接下就是Python 如何进行socket编程的介绍。

python通过socket库,我们可以很方便使用socket编程。

创建套接字:socket.socket(socket.family, socket_type, protocol=0)

socket_family是AF_UNIX或AF_INET, socket_type是SOCK_STREAM或SOCK_DGRAM。protocol默认为0

 

先来一个tcp例子:

SimpleSocketServer.py

实现了一个最多同时处理5个socket client 的简单socket server

#coding:'utf-8'
import socket
import threading
import sys

BUFSIZE = 1024

class SimpleSocketServer():

    def __init__(self, ip, port):
        self.ss = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self.addr = (ip, port)
        self.stop = False

    def start(self):
        self.ss.bind(self.addr)
        self.ss.listen(5)
        try:
            while True:
                if self.stop:
                    break
                cs, addr = self.ss.accept()
                th_cs = threading.Thread(target=self.cs_handler, args=(cs, addr))
                th_cs.start()
        except KeyboardInterrupt:
            self.ss.close()
            sys.exit()

    def stop_server(self): 
        self.stop = True  

    def cs_handler(self, cs, addr):
        print 'client[%s] has client to server...' % str(addr)
        try:
            while True:
                data = cs.recv(BUFSIZE)
                if not data:
                    break
                cs.send('hello, you send data is [%s]' % data)
        except KeyboardInterrupt:
            sys.exit()


if __name__ == '__main__':
    SimpleSocketServer('127.0.0.1', 33233).start()

SimpleSocketClient.py

#coding:'utf-8'
import socket
import thread
import sys

if __name__ == '__main__':
    cs = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
    cs.connect(('127.0.0.1',33233))
    
    while True:
        try:
            INPUT = raw_input('you input >')
            cs.send(INPUT)
            data = cs.recv(1024)
            print 'from server: %s' % data
        except KeyboardInterrupt:
            cs.close()
            sys.exit(0)
            break
        except EOFError:
            print 'Unknown End of file!'
            continue

 

 特别说明:

当超过一个以上的client连到socket server时,在终端会看到

λ python SimpleSocketServer.py
client[('127.0.0.1', 49308)] has client to server...
client[('127.0.0.1', 49568)] has client to server...

这是为什么呢?

一旦TCP服务器接受了一个连接,就会返回(accept()实现)一个独立的客户端套接字,用来与即将到来的消息进行交互。这时原始服务器套接字就能继续接受新的客户端连接请求了。

 

下面是一个UDP的例子:

udp服务器:

#coding:'utf-8'
import socket
import threading
import sys

BUFSIZE = 1024

class SimpleUDPServer():

    def __init__(self, ip, port):
        self.ss = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        self.addr = (ip, port)
        self.stop = False

    def start(self):
        self.ss.bind(self.addr)
        
        try:
            while True:
                if self.stop:
                    break
                data, addr = self.ss.recvfrom(BUFSIZE)
                print 'udp server recvfrom client[%s]:%s ' % (str(addr), data)
                self.ss.sendto('hello, you send data is [%s]' % data, addr)
        except KeyboardInterrupt:
            self.ss.close()
            sys.exit()

    def stop_server(self): 
        self.stop = True  


if __name__ == '__main__':
    SimpleUDPServer('127.0.0.1', 33233).start()
 

udp客户端:

#coding:'utf-8'
import socket
import thread
import sys

if __name__ == '__main__':
    cs = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
    addr = ('127.0.0.1',33233)
    
    while True:
        try:
            INPUT = raw_input('you input >')
            cs.sendto(INPUT, addr)
            data, addr = cs.recvfrom(1024)
            print 'from server[%s]: %s' % (str(addr),data)
        except KeyboardInterrupt:
            cs.close()
            sys.exit(0)
            break
        except EOFError:
            print 'Unknown End of file!'
            continue

当udp有接受到client连接到的数据时:

λ python SimpleUDPServer.py
udp server recvfrom client[('127.0.0.1', 57959)]:;;
udp server recvfrom client[('127.0.0.1', 57959)]:ffdfdf
udp server recvfrom client[('127.0.0.1', 63667)]: 111
udp server recvfrom client[('127.0.0.1', 63667)]:fdfdf

 

UDP和TCP服务器之间的另一个显著 差异是,因为数据报套接字是无连接的,所以就没有为了成功通信而使一个客户端连接到一个独立的套接字“转换”的操作

posted @ 2017-07-22 17:49  yihailin  阅读(540)  评论(0编辑  收藏  举报