1.什么是socket
在应用层和传输层之间,是一组封装了TCP/UDP协议的接口,让socket组织数据和传输数据。
2.客户端和服务器都要使用socket对象
缓冲区:
1、作为发送方,数据一定先给到操作系统,而操作系统不可能同时处理,所以操作系统需要一个缓冲区,先将数据放到缓冲区,操作系统会自己到缓冲区拿数据进行处理 2、作为接收方,数据也是先入操作系统的缓冲区,操作系统到缓冲区拿取数据给应用程序
s.bind()
s.listen()
s.accept()
#客户端
s.connect()
#公共函数
s.recv()
s.send() #发送tcp数据
s.senall()#发送完整的tcp数据
s.recvrom() #接收udp数据
s.sento() #发送udp数据
3.基于TCP的socket
(1)基础版
#服务器端
import socket
server=socket.socket()
server.bind(("127.0.0.1",9899))
server.listen()
client,addr=server.accept()
data=client.recv(1024)
print("收到客户端发来的数据%s"%data.decode("utf-8"))
client.send(data)
client.close()
server.close()
#客户端
import socket
client=socket.socket()
client.connect(("127.0.0.1",9899))
client.send("hello 服务器".encode("utf-8"))
data=client.recv(1024)
print("收到服务器%s"%data.decode("utf-8"))
client.close()
(2)循环版
#服务器端循环收发
import socket
server=socket.socket()
server.bind(("127.0.0.1",9999))
server.listen()
while True:
client,addr=server.accept() #可以不断地接收新连接
while True:
try:
data=client.recv(1024)
if not data:
client.close()
break
print("收到客户端发来的数据%s"%data.decode("utf-8"))
client.send(data)
except ConnectionResetError:
print("客户端强行关闭了连接")
client.close()
break
client.close()
server.close()
#客户端循环收发
import socket
client=socket.socket()
client.connect(("127.0.0.1",9999))
while True:
msg=input(">>>").strip()
client.send(msg.encode("utf-8"))
data=client.recv(1024)
print("收到服务器%s"%data.decode("utf-8"))
client.close()
(3)异常处理
#服务器
import socket
server=socket.socket()
server.bind(("127.0.0.1",8889))
server.listen()
client,addr=server.accept()
while True:
try:
data=client.recv(1024)
if not data:
print("对方已关闭")
break
print("来自客户端的-----%s"%data.decode("utf-8"))
client.send(data.upper())
except ConnectionResetError:
print("对方异常关闭连接")
client.close()
server.close()
#客户端
import socket
client=socket.socket()
client.connect(("127.0.0.1",8889))
client.send(input(">>>").encode("utf-8"))
data=client.recv(1024)
print("来自服务器的----%s"%data.decode("utf-8"))
client.close()
4.基于UDP的socket
#服务器
import socket
server=socket.socket(socket.AF_INET,socket.SOCK_DGRAM,proto=0)
server.bind(("127.0.0.1",5666))
while True:
data,addr=server.recvfrom(1024) #阻塞,直到收到数据为止
print("收到来自%s的消息:%s"%(data.decode("utf-8"),addr[0]))
server.sendto(data.upper(),addr)
server.close()
#客户端1
import socket
client=socket.socket(socket.AF_INET,socket.SOCK_DGRAM,0)
while True:
data=input(">>>").encode("utf-8")
client.sendto(data,("127.0.0.1",5666))
d,addr=client.recvfrom(1024)
print(d.decode("utf-8"))
client.close()
#客户端2
import socket
client=socket.socket(socket.AF_INET,socket.SOCK_DGRAM,0)
while True:
data=input(">>>").encode("utf-8")
client.sendto(data,("127.0.0.1",5666))
d,addr=client.recvfrom(1024)
print(d.decode("utf-8"))
client.close()
5、半连接池
产生半连接的两种情况:
2、服务器来不及处理客户端的连接请求。
有一种攻击叫syn洪水攻击,就是不断产生半连接,让服务器无法处理请求。
半连接池的作用:
半连接池就是一个容器,系统会自动将半连接放入这个容器中,可以避免半连接过多导致 资源耗光。
import socket
server=socket.socket()
server.listen(5) #表示最多可以等5个连接
#服务器
import socket,time
server=socket.socket()
server.bind(("127.0.0.1",6667))
server.listen(1)
while True:
time.sleep(0.5)
server.close()
#客户端1
import socket
client=socket.socket()
client.connect(("127.0.0.1",6667))
while True:
client.send(input(">>>").encode("utf-8"))
data=client.recv(1024)
print(data.decode("utf-8"))
client.close()
#客户端2
import socket
client=socket.socket()
client.connect(("127.0.0.1",6667))
while True:
client.send(input(">>>").encode("utf-8"))
data=client.recv(1024)
print(data.decode("utf-8"))
client.close()
分别运行服务器----客户端1----客户端2 结果为: