python基础之socket

1、TCP sorcket:

server side(服务器端):

 1 import SocketServer
 2 class MyTCPHandler(SocketServer.BaseRequestHandler):
 3     def handle(self):
 4         self.data=self.request.recv(1024).strip()
 5         print "{} wrote".format(self.client_address[0])
 6         print self.data
 7         self.request.sendall(self.data.upper())
 8 if __name__=="__main__":
 9     HOST,PORT="localhost",9999
10     server=SocketServer.TCPServer((HOST,PORT),MyTCPHandler)
11     server.serve_forever()    

解释:

第1句引进相关模块;
第2句定义类MyTCPHandler,它是继承自SocketServer的BaseRequestHandler类,该类还有相关的子类,下面会用到;
第3句重写基类的handle()方法,有很多属性可以直接用,比如self.request,请求,self.request.recv(1024).strip()的意思是从客户端的请求那得到最大1kb的数据,并且数据.strip(),去掉前后的空格,中间的不会去掉的;
self.client_adress是客户端的地址;
第7句是把得到的数据转换成大写发给客户端;
第8句是只有在直接运行当前程序是才会运行到的;
HOST、PORT是主机地址和端口号;
第10句就是创建一个server对象,是基于TCPServer类创建的;
11句是启动服务监听的意思;

上面是一种创建TCP server的方法,下面还有一种基于BaseRequestHandler基类StreamRequestHandler,当然它还有一个基类DatagramRequestHandler,两者有区别。

 1 import SocketServer
 2 class MyTCPHandler(SocketServer.StreamRequestHandler):
 3     def handle(self):
 4         self.data=self.rfile.readline().strip()
 5         print "{} wrote".format(self.client_address[0])
 6         print self.data
 7         self.wfile.write(self.data.upper())
 8 if __name__=="__main__":
 9     HOST,PORT="localhost",9999
10     server=SocketServer.TCPServer((HOST,PORT),MyTCPHandler)
11     server.serve_forever()

基本上与上面的相同,但是毕竟StreamRequestHandler是BaseRequestHandler的基类,所以有一些新的方法。

第4行,self.rfile.readline(), self.rfile类型是socket._fileobject,读写模式是"rb",方法有:read,readline,readlines,write(data),writelines(list),close,flush
readline()方法会多次调用recv()方法,直到读取一行;其它的基本类似。

the client side(客户端)

 1 import socket
 2 import sys
 3 HOST,PORT="localhost",9999
 4 data=" ".join(sys.argv[1:])
 5 sock=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
 6 try:
 7     sock.connect((HOST,PORT))
 8     sock.sendall(data+"
")
 9     received=sock.recv(1024)
10 finally:
11     sock.close()
12 print "Sent:  {}".format(data)
13 print "Received:  {}".format(received)
14 input()

重点:建立一个socket对象sock,socket.SOCK_STREAM说明建立的是一个TCP socket,用socket.SOCK_DGRAM是UDP socket。

sock.connect()方法是与主机建立连接,可见tcp协议是面向连接的可靠地通信协议,这正是tcp与udp协议的不同,udp协议是非面向连接的不可靠的协议,udp发送数据之前并不会与对方建立连接,而是直接发给对方。UDP适用于一次只传送少量数据、对可靠性要求不高的应用环境。
比如,我们经常使用“ping”命令来测试两台主机之间TCP/IP通信是否正常,其实“ping”命令的原理就是向对方主机发送UDP数据包,然后对方主机确认收到数据包,如果数据包是否到达的消息及时反馈回来,那么网络就是通的。例如,在默认状态下,一次“ping”操作发送4个数据包。大家可以看到,发送的数据包数量是4包,收到的也是4包(因为对方主机收到后会发回一个确认收到的数据包)。这充分说明了UDP协议是面向非连接的协议,没有建立连接的过程。正因为UDP协议没有连接的过程,所以它的通信效率高;但也正因为如此,它的可靠性不如TCP协议高。
QQ就使用UDP发消息,因此有时会出现收不到消息的情况。

下面我们就用python来实现UDP的通信协议。

udp服务器端:

 1 import SocketServer
 2 class MyUDPHandler(SocketServer.BaseRequestHandler):
 3     def handle(self):
 4         data=self.request[0].strip()
 5         socket=self.request[1]
 6         print "{} wrote".format(self.client_address[0])
 7         print data
 8         socket.sendto(data.upper(),self.client_address)
 9 if __name__=="__main__":
10     HOST,PORT="localhost",9999
11     server =SocketServer.UDPServer((HOST,PORT),MyUDPHandler)
12     server.serve_forever()

解释:udp的server与tcp的有一定的区别,它的self.request含有一个data和一个socket,分别用self.request[0]和self.request[1]获取,由于udp是面向非连接的协议,所以要用sendto()方法,并且要加上客户端的地址。

udp客户端:

1 import socket
2 import sys
3 HOST,PORT="localhost",9999
4 data=" ".join(sys.argv[1:])
5 sock=socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
6 sock.sendto(data+"
",(HOST,PORT))
7 received=sock.recv(1024)
8 print "Sent:  {}".format(data)
9 print "Received:  {}".format(received)

可以看出与tcp的客户端相比,udp的sock并没有连接过程,直接发送的数据。

运行,点击运行服务器端.py的文件,然后在命令行下:python d:/py/client.py hello world  (根据自己的文件地址写命令)回车就ok了,可以看到客户端服务器端都有输出数据。

原文地址:https://www.cnblogs.com/nannanITeye/p/3271393.html