【Socket】Python UDP和TCP的socket实例
Socket
Socket又称”套接字”,应用程序通常通过”套接字”向网络发出请求或者应答网络请求。 具体定义看百科
socket有两种,一种基于UDP,一种基于TCP。UDP是面向非连接的,传递的是数据报,每次传递都要指定目的地址端口;而TCP是面向连接的,经过三次握手协议建立起连接,所以不用每次都指定目的地址端口。当然还有很多的区别,这里就不一一列举。
一般服务器端和客户端各有一个socket,你可以将它看成是一个网络接口,将你的请求转化成底层数据,把收到的数据转化成高级的数据对象。
在Python中用于socket编程的包是socket
,这是一个自带的包。
UDP socket
UDP Server端
#coding=utf-8
import socket
import time
HOST = 'localhost' #主机,因为是本机所以是localhost,或者127.0.0.1也可以
BUFFSIZE = 1024 #每次读取数据的缓存区大小
PORT = 8802 #端口,也就是客户端要连接的端口
ADDR = (HOST,PORT) #将主机地址和端口组成一个tuple形式的地址
UDPSerSocket = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
UDPSerSocket.bind(ADDR)
print('waiting for connect...')
while True:
data,addr = UDPSerSocket.recvfrom(BUFFSIZE)
print 'Received',data,'from',addr,'in [%s]'%time.ctime()
UDPSerSocket.sendto('[%s]:%s'%(time.ctime(),data),addr)
UDPSerSocket.close()
说明:
UDPSerSocket = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
中两个参数,第一个是指定以internet地址连接,第一个参数还有一个值是AF_UNIX
,但是一般都不会用到,至少我还没用到过。第二个参数是指定以何种方式传输,socket.SOCK_DGRAM
是以数据报的形式传输,也就是对应UDP方式,TCP方式是socket.socket.SOCK_STREAM
。UDPSerSocket.bind(ADDR)
是绑定地址,服务器端的socket必须执行这一步,计算机才知道这个socket对应那个端口,并可以在这个端口监听。服务器端的socket一般都会有一个
while True
的循环,用于接收完数据之后马上等待下一个数据。UDPSerSocket.recvfrom(BUFFSIZE)
是接收数据的方法,接受到的是一个data
数据和发送数据的地址addr
。之前我们说过UDP方式是每一次都必须指定地址,所以这里获取到一个地址可以在下一步的发送方法UDPSerSocket.sendto('[%s]:%s'%(time.ctime(),data),addr)
中用到。最后,用完socket之后记得记性
close()
方法释放
UDP Client端
#coding=utf-8
import socket
HOST = 'localhost'
PORT = 8802
ADDR = (HOST,PORT)
BUFFSIZE = 1024
UDPcliSocket = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
while True:
data = raw_input('>')
if not data:
break;
UDPcliSocket.sendto(data,ADDR)
datarecv,addr = UDPcliSocket.recvfrom(BUFFSIZE)
if not datarecv:
break
print datarecv
UDPcliSocket.close()
说明:
Client和Server建立socket对象的方法都是一样的,不同的是Client端不需要绑定
bind()
,因为Client是一般情况下是主动连接的一方,而不是等待的一方。Client端的接收和发送方法和Server是完全一样的。
TCP socket
TCP Server端
#coding=utf-8
import socket
import time
HOST = 'localhost'
PORT = 8081
BUFFSIZE = 1024
ADDR = (HOST,PORT)
TCPSerSocket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
TCPSerSocket.bind(ADDR)
TCPSerSocket.listen(5)
while True:
print "waiting for connection..."
tcpCliSocket,addr = TCPSerSocket.accept()
print '...connected from:',addr
while True:
data = tcpCliSocket.recv(BUFFSIZE)
if not data:
break
tcpCliSocket.send('[%s] %s'%(time.ctime(),data))
print [time.ctime()],":",data
tcpCliSocket.close()
TCPSerSocket.close()
说明:
TCP与UDP的Server端建立socket对象差不多,不同的是在
socket.socket(socket.AF_INET,socket.SOCK_STREAM)
第二个参数指定为socket.SOCK_STREAM
,同样也需要绑定地址端口。,还有TCP的ServerSocket还需要一个listen(5)
方法,表示监听,不加会报错。我们说TCP是面向连接的,所以在Client端连接到Server后并不会立刻断开,而为了能双方通信,Server会通过
tcpCliSocket,addr = TCPSerSocket.accept()
收到一个ClientSocket对象,通过操作ClientSocket对象来完成接收、发送操作。TCP接收方法是
recv
与UDP的recvfrom
不同,其实想想还是挺容易理解的,UDP的recvfrom
方法除了得到data
之外,还能得到addr
,所以才有from,而TCP早就已经得到ClientSocket对象,当然也通过accept()
得到了addr
,所以就没有from咯。TCP的send
和UDP的sendto
也可如此理解。当然还是不要忘记执行
close()
方法,也不要忘了关闭ClientSocket
。
TCP Client端
#coding = utf-8
import socket
import time
HOST = 'localhost'
PORT = 8081
BUFFSIZE = 1024
ADDR = (HOST,PORT)
TCPCliSocket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
TCPCliSocket.connect(ADDR)
while True:
data = raw_input('>')
if not data:
break
TCPCliSocket.send(data)
data = TCPCliSocket.recv(BUFFSIZE)
if not data:
break
print '%s'%data
说明:
TCP与UDP的ClientSocket不同之处在于
TCPClientSocket
要先建立连接,所以要执行connect()
方法,为什么?因为TCP是面向连接的。Client端的发送和接收方法与TCP的Server相同,
send()
和recv()
Client端不会像Server端那样接收到对方的Socket的,为什么,因为不需要!一般Client是主动连接Server,就是用
connect()
,那么连接后Client就把自己的ClientSocket传给Server,Server通过它来操作发送接收,而Client也就用ClientSocket接收和发送咯,你可以将ClientSocket看成一个管道,通过这个管道来沟通Server和Client。
总结:
Server端都要用
bind()
绑定地址和端口。区别TCP和UDP的是在建立ServerSocket对象时第二个参数不同,TCP是
socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
,而UDP是socket.socket(socket.AF_INET,socket.SOCK_STREAM)
。TCP的Server还需要有
listen()
方法监听。TCP的Server端会通过
accpet()
方法得到addr
和ClientSocket
,通过ClientSocket
的send()
和recv()
方法实现发送和接收。UDP的发送和接收方法是
sendto()
和recvfrom
,TCP的发送和接收方法是send
和recv
,注意区分。
代码下载:
博文中代码点此下载