一.socket套接字
socket(简称 套接字 ) 是进程间通信的⼀种⽅式,它与其他进程间通信的⼀个主要不同是:它能实现不同主机间的进程间通信,我们⽹络上各种各样的服务⼤多都是基于 Socket 来完成通信的。套接字可以分为两种:
(1)TCP套接字是面向连接的套接字,这意味着在开始通信之前必须先建立一个连接。
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) #创建一个TCP套接字
(2)UDP套接字是无连接的套接字,也称为数据报,即在开始通信之前并不需要建立连接。
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) #创建一个套接字
面向连接的套接字提供一种序列化的、可靠的和不重复的数据交付,而没有记录边界。这基本上意味着每条消息可以拆分成多个片段,并且每一条消息都能够到达目的地,然后它们将按照顺序组合在一起,最后将完整的消息传递给正在等待的应用程序。
反之,无连接的套接字在数据传输过程中无法保证它的顺序性、可靠性和不重复性,并且在数据传输过程中还有可能出现数据丢失的情况。同时,相对于面向连接到套接字,无连接套接字的开销更低,成本也更加低廉,通常能够提供更好的性能。
二.代码实现
1.udp
udp发数据
from socket import *
udpSocket = socket(AF_INET, SOCK_DGRAM) #1. 创建套接字
sendAddr = ('192.168.1.103', 8080) #2. 准备接收⽅的地址与端口
sendData = raw_input("请输⼊要发送的数据:") #3. 从键盘获取数据
udpSocket.sendto(sendData, sendAddr) #4. 发送数据到指定的电脑上
udpSocket.close() #5. 关闭套接字
udp接收数据
#coding=utf-8
from socket import *
udpSocket = socket(AF_INET, SOCK_DGRAM) #1. 创建套接字
bindAddr = ('', 7788) #2. udp绑定信息,绑定本地的相关信息,如果⼀个⽹络程序不绑定,则系统会随机分配ip地址和端⼝号,ip⼀般不⽤写,表示本机的任何⼀个ip
udpSocket.bind(bindAddr)
recvData = udpSocket.recvfrom(1024) #3. 等待接收对⽅发送的数据,1024表示本次接收的最⼤字节数
print recvData #4. 显示接收到的数据
udpSocket.close() #5. 关闭套接字
典型例子:模拟QQ完成一个全双工的QQ聊天程序
from threading import Thread
from socket import *
#1. 收数据,然后打印
def recvData():
while True:
recvInfo = udpSocket.recvfrom(1024)
print(">>%s:%s"%(str(recvInfo[1]), recvInfo[0]))
#2. 检测键盘,发数据
def sendData():
while True:
sendInfo = raw_input("<<")
udpSocket.sendto(sendInfo.encode('utf-8'), (destIp, destPort))
udpSocket = None
destIp = ""
destPort = 0
def main():
global udpSocket
global destIp
global destPort
destIp = raw_input("对方的ip:")
destPort = int(raw_input("对方的ip:"))
udpSocket = socket(AF_INET, SOCK_DGRAM)
udpSocket.bind(("", 12345))
tr = Thread(target=recvData)
ts = Thread(target=sendData)
tr.start()
ts.start()
tr.join()
ts.join()
if __name__ == "__main__":
main()
2.tcp
tcp server
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import socket,threading,time
def tcplink(sock, addr):
print('Accept new connection from %s:%s...' % addr)
sock.send(b'Welcome!')
while True:
data = sock.recv(1024)
time.sleep(1)
if not data or data.decode('utf-8') == 'exit':
break
sock.send(('Hello, %s!' % data.decode('utf-8')).encode('utf-8'))
sock.close()
print('Connection from %s:%s closed.' % addr)
def ttry():
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 监听端口(服务器IP与端口)
s.bind(('127.0.0.1', 9999))
s.listen(5) #进行监听
print('Waiting for connection...')
while True:
# 接受一个新连接:
sock, addr = s.accept()
# 创建新线程来处理TCP连接:
t = threading.Thread(target=tcplink, args=(sock, addr)) #分配一个线程去处理
t.start()
time.sleep(10)
exit(0)
if __name__ == '__main__':
ttry()
tcp client
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import socket
def ttry():
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 建立连接:
s.connect(('127.0.0.1', 9999))
# 接收欢迎消息:
print(s.recv(1024).decode('utf-8'))
for data in ['Michael', 'Tracy', 'Sarah']:
# 发送数据:
s.send(data)
print(s.recv(1024).decode('utf-8'))
s.send(b'exit')
s.close()
if __name__ == '__main__':
ttry()
(相比之下,tcp通信需要一个连接的过程)