Appearance
Socket
UDP通信
可以使用python里面的socket模块进行创建一个socket
python
import socket
socket.socket(AddressFamily, Type)
AddressFamily: AF_INET用于Internet进程里面的通讯, AF_UNIX用于同一台机器的通信
Type: 实际使用的协议, SOCK_STREAM流式套接字, 一般使用的是TCP, SOCK_DGRAM, 数据套接字, 一般用UDP
python
import socket
if __name__ == "__main__":
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(("www.baidu.com", 80))
s.send(b"GET / HTTP/1.1\r\nHost: www.baidu.com\r\nConnection: close\r\n\r\n")
buffer = []
while True:
d = s.recv(1024)
if d:
buffer.append(d)
else:
break
data = b"".join(buffer)
s.close()
# 分离header和html
header, html = data.split(b"\r\n\r\n", 1)
print(header.decode("utf-8"))
with open("baidu.html", "wb") as f:
f.write(html)
s.close()
函数
sendto发送信息
python
socket.sendto(bytes, address)¶
python
import socket
if __name__ == "__main__":
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
dest_addr = ("192.168.65.1", 8080)
s.sendto(b"GET / HTTP/1.1\r\nHost: www.baidu.com\r\nConnection: close\r\n\r\n", dest_addr)
s.close()
这一个直接发送的时候使用的是UDP, 在发送的时候这一个数据必须是bytes类型的, 发送的时候也可以使用一个字符串
.encode('utf-8')
进行编码, 获取的数据使用.decode("utf-8")
进行解码
发送数据的时候会使用一个随机的端口, 每一次程序里面只会申请一次端口
recvfrom接收udp数据
python
socket.recvfrom(bufsize[, flags])
python
import socket
if __name__ == "__main__":
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
dest_addr = ("192.168.65.1", 8080)
s.sendto(b"GET /v1/images/search HTTP/1.1\r\nHost: www.baidu.com\r\nConnection: close\r\n\r\n", dest_addr)
data, addr = s.recvfrom(1024)
print(data.decode())
print(addr)
s.close()
bashPS E:\JHY\python\2024-5-10-internet> python -u "e:\JHY\python\2024-5-10-internet\main.py" hello ('192.168.65.1', 8080)
使用阻塞的方式进行获取数据, 接收的数据是一个元组, 里面分别的是获取的数据以及这一个数据的来源
See the Unix manual page recv(2) for the meaning of the optional argument flags; it defaults to zero. (The format of address depends on the address family — see above.)
bind绑定端口
python
socket.bind(address)
参数是一个元组, 第一个是元素ip字符串, 第二个元素是端口, 这一个ip可以为空, 会使用本机的ip
python
s.bind(("", 11451))
这一个绑定的时候需要在发送信息前面, 否则有一个自动绑定的端口, 不能再进行绑定
非阻塞
python
# 设置套接字为阻塞或非阻塞模式:如果 flag 为 false,则将套接字设置为非阻塞,否则设置为阻塞。
# socket.setblocking(flag)
# 如果value赋为 0,则套接字将处于非阻塞模式。如果指定为 None,则套接字将处于阻塞模式。
# socket.settimeout(value)
# 阻塞
sock.setblocking(True)
sock.settimeout(None)
# 非阻塞
sock.setblocking(False)
sock.settimeout(0.0)
UDP广播
发送给这一个局域网里面的每一个电脑的某一个端口发送一个数据
python
if __name__ == "__main__":
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
# 设置广播选项
s.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
# 广播地址
dest_info = ('<broadcast>', 11451)
while True:
data = input("请输入要广播的内容:")
s.sendto(data.encode(), dest_info)
主机号是255的是广播地址
TCP通信
- 客户端
- 建立套接字
- 连接对方, connect
- 发送数据, send
- 接收数据, recv
- 关闭套接字, close
- 服务器
- 建立TCP套接字
- 绑定ip以及端口, bind
- 等待连接, listen
- 接收连接, accept
- 发送接收数据, recv/send
- 关闭连接close
python
import socket
if __name__ == "__main__":
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 建立连接
s.connect(("192.168.65.1", 11451))
while True:
data = input("请输入要发送的数据:")
s.send(data.encode('gbk'))
if data == "exit":
break
s.close()
print("连接已关闭")
函数
send发送
recv接收
python
ret = s.recv(1024)
print(ret.decode('gbk'))
这时候获取的数据只有对方发送的数据
accept等待连接
python
import socket
if __name__ == "__main__":
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind(("127.0.0.1", 11451))
s.listen(5)
print("服务器启动成功")
while True:
client, addr = s.accept()
print("连接地址:", addr)
while True:
data = client.recv(1024)
if data == b"exit":
break
print(data.decode())
client.send("已收到".encode())
client.close()
print("连接已关闭")
服务连接的时候需要等待客户端断开连接, 否则会出现错误, 四次挥手的TIME_WAIT阶段会由服务器进行, 这一个资源需要等待2msl
对方发送的数据是一个空字符串的时候, 这一个连接是中断了