Socket网络编程
Socket
:通过网络完成进程间通信的方式Socket
的英文原义是“插孔”。通常也称作"套接字“
- Socket本质是编程接口(API): Socket 是对 TCP/IP 协议的封装,Socket 只是个编程接口不是协议,通过 Socket 我们才能使用 TCP/IP 协议簇(程序员层面)
- TCP/IP也要提供可供程序员做网络开发所用的接口,这就是Socket编程接口;HTTP是轿车,提供了封装或者显示数据的具体形式;Socket是发动机,提供了网络通信的能力
- 最重要的是,Socket是面向客户/服务器模型而设计的,针对客户和服务器程序提供不同的Socket系统调用
- 套接字之间的连接过程可以分为三个步骤:服务器监听,客户端请求,连接确认
Socket编程-udp
- UDP --- User Data Protocol用户数据报协议, 是⼀个⽆连接的简单的⾯向数据报的传输层协议。
UDP
不提供可靠性, 它只是把应⽤程序传给IP
层的数据报发送出去, 但是并不能保证它们能到达⽬的地。 由于UDP
在传输数据报前不⽤在客户和服务器之间建⽴⼀个连接, 且没有超时重发等机制, 故⽽传输速度很快,UDP
⼀般⽤于多点通信和实时的数据业务, ⽐如:语⾳,⼴播,视频,QQ
,TFTP
(简单⽂件传送)
udp套接字服务端与客户端实例
服务器端
import socket
server=socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
server.bind(('127.0.0.1',8080))
while True:
msg,client_addr=server.recvfrom(1024) #(接收客户端消息和客户端ip和端口)如果接收的数据量小于发送的数据量就会出现丢包的问题
server.sendto(msg.upper(),client_addr) #发送数据内容和客户端ip和端口
server.close()
客户端
import socket
client=socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
ip_port=('127.0.0.1',8080)
while True:
msg=input('>>>').strip() #udp是数据报协议,自带报头,每发一次数据对应一条收,udp是无连接的即使收空能发送,因为发空也会有一个报头
client.sendto(msg.encode('utf-8'),ip_port) #每次发送数据量最好不要超过512个字节,无连接意味着发送要指定对方的ip和port
data,server_addr=client.recvfrom(1024) #接收会拿到接收对方发送的数据和对方的ip和port,是一个元组的形式,所以解包即可
print(data)
client.close()
Socket编程-tcp
TCP(Transmission Control Protocol,传输控制协议是面向连接的协议,也就是说,在收发数据前,必须和对方建立可靠的连接,一个TCP连接必须要经过三次“对话”才能建立起来,其中的过程非常复杂,–可以理解为打电话,先建立通道.
tcp是基于连接的,必须先启动服务端,然后在启动客户端连接服务端
tcp服务端
ss = socket() #创建服务器套接字
ss.bind() #把地址绑定到套接字
ss.listen() #监听链接
inf_loop: #服务器无限循环
cs = ss.accept() #接受客户端链接
comm_loop: #通讯循环
cs.recv()/cs.send() #对话(接收与发送)
cs.close() #关闭客户端套接字
ss.close() #关闭服务器套接字(可选)
tcp客户端
cs = socket() # 创建客户套接字
cs.connect() # 尝试连接服务器
comm_loop: # 通讯循环
cs.send()/cs.recv() # 对话(发送/接收)
cs.close() # 关闭客户套接字
完整版TCP服务端
服务端
from socket import *
tcpSerSocket = socket(AF_INET, SOCK_STREAM)
address = (‘’, 7788)
tcpSerSocket.bind(address)
tcpSerSocket.listen(5)#设置最大连接数
newSocket, clientAddr = tcpSerSocket.accept()
# 如果有新的客户端来链接服务器, 那么就产⽣⼀个新的套接字# newSocket⽤来为这个客户端服务(10086小妹)
# tcpSerSocket就可以省下来等待其他新客户端的链接
# 接收对⽅发送过来的数据, 最⼤接收1024个字节
recvData = newSocket.recv(1024) #接收tcp数据
# 发送⼀些数据到客户端
newSocket.send(“thank you !”) #发送tcp数据
# 关闭为这个客户端服务的套接字, 只要关闭了, 就意味着为不能再为这个客户端服务了
newSocket.close()
# 关闭监听套接字, 只要这个套接字关闭了, 就意味着整个程序不能再接收任何新的客户端的连接
tcpSerSocket.close()
from socket import *
clientSocket = socket(AF_INET, SOCK_STREAM)
serAddr = ('192.168.1.17', 7788)
#链接服务器
clientSocket.connect(serAddr)
clientSocket.send(b"hello")
recvData = clientSocket.recv(1024)
print("接收到的数据为:", recvData)
clientSocket.close()
多进程服务器
from socket import *
from multiprocessing import *
from time import sleep# 处理客户端的请求并为其服务
def dealWithClient(newSocket,destAddr):
while True:
recvData = newSocket.recv(1024)
if len(recvData)>0:
print('recv[%s]:%s'%(str(destAddr), recvData))
else:
print('[%s]客户端已经关闭'%str(destAddr))
break
newSocket.close()
def main():
serSocket = socket(AF_INET, SOCK_STREAM)
serSocket.setsockopt(SOL_SOCKET, SO_REUSEADDR , 1)
localAddr = ('', 7788)
serSocket.bind(localAddr)
serSocket.listen(5)
try:
while True:
print('-----主进程, , 等待新客户端的到来------’)
newSocket,destAddr = serSocket.accept()
print(‘-----主进程, , 接下来创建⼀个新的进程负责数据处理’)
client = Process(target=dealWithClient, args=(newSocket,destAddr)) client.start()
#因为已经向⼦进程中copy了⼀份(引⽤) , ⽗进程中这个套接字也没有用处了
#所以关闭
newSocket.close()
finally:
#当为所有的客户端服务完之后再进⾏关闭,
表示不再接收新的客户端的链接
serSocket.close()
if __name__ == '__main__’:
main()
多线程服务器
from socket import *
from threading import Thread
from time import sleep
# 处理客户端的请求并执⾏事情
def dealWithClient(newSocket,destAddr):
while True:
recvData = newSocket.recv(1024)
if len(recvData)>0:
print('recv[%s]:%s'%(str(destAddr), recvData))
else:
print('[%s]客户端已经关闭'%str(destAddr))
break
newSocket.close()
def main():
serSocket = socket(AF_INET, SOCK_STREAM)
serSocket.setsockopt(SOL_SOCKET, SO_REUSEADDR , 1)
localAddr = ('', 7788)
serSocket.bind(localAddr)
serSocket.listen(5)
try:
while True:
print(‘-----主进程, , 等待新客户端的到来------’)
newSocket,destAddr = serSocket.accept()
print(‘主进程接下来创建⼀个新的线程负责处理 ‘, str(destAddr)))
client = Thread(target=dealWithClient, args=(newSocket,destAddr))
client.start()
#因为线程中共享这个套接字, 如果关闭了会导致这个套接字不可⽤,
#但是此时在线程中这个套接字可能还在收数据, 因此不能关闭
#newSocket.close()
finally:
serSocket.close()
if __name__ == '__main__’:
main()