ip地址和端口号
ip地址:用来唯一表示网络设备 端口号:主要区分主机上的不同应用
tcp和udp
tcp: 可靠传输,基于数据流的传输,自动检测并回传丢失数据包,发送和接收数据顺序一致,但是要求收发双方扮演不同角色,既客户端和服务端,服务端只能被动等待客户端连接,不会主动发起请求
udp: 不可靠传输,以报文为单位来收发数据,不会自动回传丢失的数据包因此不能保证对方能够接收到,正是缺少这些检查,udp通常具有更低的延迟并占用更少的系统资源,因此适用于视频语音通话等实时性较高的应用。
服务端
import socket
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.bind(("0.0.0.0", 1234))
s.listen()
c, addr = s.accept()
with c:
print(addr, 'connected')
while True:
data = c.recv(1024)
if not data:
break
c.sendall(data)
客户端
import socket
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.connect(("127.0.0.1", 1234))
s.sendall(b'hello, Ross!')
data = s.recv(1024)
print('Received:', repr(data))
存在问题
这里的服务端只能处理一个客户端的请求,要并发与多个客户端进行通信有一下集中方法。
1. 多线程Socket服务器
import socket
import threading
def handle_client(c, addr):
print(addr, 'connected.')
while True:
data = c.recv(1024)
if not data:
break
c.sendall(data)
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.bind(('0.0.0.0', 1024))
s.listen()
while True:
c, addr = s.accept()
t = threading.Thread(target=handle_client, args=(c, addr))
t.start()
多线程存在问题: 由于GIL存在,python本身不存在真正并发,并且线程自身也会占用额外的系统资源
2. selectors——高级I/O复用库
3. selectors——异步I/O
简单的HTTP应用
HTTP是TCP协议的一个典型应用,也是浏览器与服务器交互的主要方式,通常服务器会监听80端口等待客户端连接,客户端连接上服务器后,首先要确定要访问的资源,然后客户端会提供一系列额外信息,每一条以冒号分隔的键值对,也包括浏览器版本,称之为消息的头部,随后空行,然后是消息主体。 服务端会以同样方式,回应客户都安的请求。 首先是一行状态行,里面包含一个状态码,200代表请求成功 然后键值对,资源类型服务器信息等等 在后面是一个空行 最后面是消息主体
import socket
import threading
import os
WEBROOT = 'webroot'
def handle_client(c, addr):
print(addr, 'connected!')
with c:
request = c.recv(1024)
headers = request.split(b'\r\n')
file = headers[0].split()[1].decode()
if file == '/':
file = '/index.html'
try:
with open(WEBROOT + file, 'rb') as f:
content = f.read()
response = b'HTTP/1.0 200 OK\r\n\r\n' +content
except FileNotFoundError:
response = b'HTTP/1.0 404 NOT FOUND\r\n\r\nFile not found'
c.sendall(response)
if __name__ == '__main__':
os.chdir(os.path.dirname((os.path.abspath(__file__))))
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.bind(('0.0.0.0', 80))
s.listen()
while True:
c, addr = s.accept()
t = threading.Thread(target=handle_client, args=(c, addr))
t.start()
根路径 其他路径
|