一.socket层
二.什么是socket
socket是应用层与TCP/IP协议族通信的中间软件抽象层,它是一组接口。在设计模式中,socket其实就是一个门面模式,它把复杂的TCP/IP协议族隐藏在socket接口后面,对用户来说,一组简单的接口就是全部,让socket去组织数据,以符合指定的协议。所以,我们无需深入理解tcp/ip协议,socket已经为我们封装好了,我们只需要遵循socket的规定去编程,写出的程序自然就是遵守tcp/udp标准的。
三.socket的作用
减少网络编程的工作量
四. 套接字家族
1.基于文件类型的套接字家族 AF_UNIX
2.基于网络类型的套接字家族 AF_INET
import socket socket.socket(socket_family,socket_type,protocal=0) socket_family 可以是 AF_UNIX 或 AF_INET。socket_type 可以是 SOCK_STREAM 或 SOCK_DGRAM。protocol 一般不填,默认值为 0。 获取tcp/ip套接字 tcpSock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 获取udp/ip套接字 udpSock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) 由于 socket 模块中有太多的属性。我们在这里破例使用了'from module import *'语句。使用 'from socket import *',我们就把 socket 模块里的所有属性都带到我们的命名空间里了,这样能 大幅减短我们的代码。 例如tcpSock = socket(AF_INET, SOCK_STREAM)
默认不填参数默认为socket.AF_INET 与 socket.SOCK_STREAM
五.socket的用法
#服务器 import socket server = socket.socket() server.bind(("127.0.0.1",16680)) server.listen() client,address = server.accept() data = client.recv(1024) print("来自客户端的数据:%s"%data.decode("utf-8")) client.send(data) client.close() #客户端 import socket client = socket.socket() client.connect(("127.0.0.1",16680)) client.send("你好".encode("utf-8")) data = client.recv(1024) print("来自服务端的数据:%s"%data.decode("utf-8")) client.close()
#服务器 import socket server = socket.socket() server.bind(("127.0.0.1",16668)) server.listen() while True: client,address = server.accept() while True: try: data = client.recv(1024) if not data: client.close() break print(data.decode("utf-8")) msg = input(">>>:").strip() client.send(msg.encode("utf-8")) except ConnectionResetError: print("客户端已经断开连接!") client.close() break #客户端 import socket client = socket.socket() client.connect(("127.0.0.1",16668)) while True: msg = input(">>>:").strip() client.send(msg.encode("utf-8")) data = client.recv(1024) print(data.decode("utf-8"))
#服务器 import socket server=socket.socket(socket.AF_INET,socket.SOCK_DGRAM,0) server.bind(("127.0.0.1",16668)) while True: data,address = server.recvfrom(1024) print("收到来自%s的数据:%s"%(address[0],data.decode('utf-8'))) msg = input(">>>:").strip() server.sendto(msg.encode("utf-8"),address) #客户端1 import socket client = socket.socket(socket.AF_INET,socket.SOCK_DGRAM,0) while True: msg = input(">>>:").strip() client.sendto(msg.encode("utf-8"),("127.0.0.1",16668)) data,address = client.recvfrom(1024) print("收到来自服务器%s的数据:%s"%(address[0],data.decode("utf-8"))) #客户端2 import socket client = socket.socket(socket.AF_INET,socket.SOCK_DGRAM,0) while True: msg = input(">>>:").strip() client.sendto(msg.encode("utf-8"),("127.0.0.1",16668)) data,address = client.recvfrom(1024) print("收到来自服务器%s的数据:%s"%(address[0],data.decode("utf-8")))
六. 半连接池
半连接是指当服务器在响应了客户端的第一次请求后,会进入等待状态,等待客户端发送的ack信息,这时候这个连接就称之为半连接。
产生半连接的两种情况:
1.客户端无法返回ACK信息
2.服务器来不及处理客户端的连接请求
有一种黑客攻击叫做syn洪水攻击,就是不断产生半连接,使服务器无法处理请求,随着半连接的增多,服务器就会奔溃。
半连接池其实就是一个容器,系统会自动将半连接放入这个容器中,可以避免半连接过多而保证资源耗光。
服务器的listen()中可以选择填参数,是指最多允许几个客户端连接服务器,即允许这么多个半连接,当有这么多个客户端时,再来一个客户端请求连接服务器,会被拒绝。