1. tcp介绍
TCP 的英文全拼(Transmission Control Protocol)简称传输控制协议,它是一种面向连接的、可靠的、基于字节流的传输层通信协议。
特点:
面向连接
传输可靠
socket (简称 套接字) 是进程之间通信一个工具,好比现实生活中的插座,所有的家用电器要想工作都是基于插座进行,进程之间想要进行网络通信需要基于这个 socket。
2. tcp开发的流程
2.1 tcp客户端的开发
1.创建客户端套接字对象 socket
2.和服务端套接字建立连接 connect
3.发送数据 send
4.接收数据 recv
5.关闭客户端套接字 close
"""
tcp客户端
基于socket的实现方式
ubuntu的编码方式utf-8
windows的编码方式gbk
"""
import socket
# 创建socket AF_INET ipv4 SOCK_STREAM tcp的方式
tcp_client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 连接服务器 包含了ip和端口
tcp_client.connect(('192.168.3.83', 6666))
# 准备数据 utf-8
data = 'hello,python'
# 数据类型的转换
data = data.encode('utf-8')
# 向服务器发发送数据
tcp_client.send(data)
# 接收数 recv要指定接收数据的大小 最大4096
recv_data = tcp_client.recv(1024)
print('未解码的数据:', recv_data)
# 接收的数据二进制的,接收完的数据要使用decode解码
recv_data = recv_data.decode('utf-8')
print(recv_data)
# 关闭
tcp_client.close()
2.2 tcp服务端的开发
1.创建服务端端套接字对象 socket
2.绑定端口号 bind
3.设置监听 listen
4.等待接受客户端的连接请求
5.接收数据 accept
6.发送数据 send
7.关闭套接字 close
"""
socket 创建套接字对象 bind 绑定端口
listen 监听 recv 接收数据
send 发送数据 close 关闭
"""
import socket
# 创建socket
tcp_server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 目前的服务器是一次性的,如果要马上释放要 设置一下socket
tcp_server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True)
# 绑定端口 没有给定ip,默认本机的ip地址
tcp_server.bind(('', 7777))
# 监听
tcp_server.listen(10)
# 连接上返回两个值,一个客户端的socket的对象一个客户端的ip
tcp_cliect_soket, ip_port = tcp_server.accept()
print(tcp_cliect_soket)
print(f'连接的客户端:{ip_port[0]},端口{ip_port[1]}')
# 接收数据
data = tcp_cliect_soket.recv(1024)
# 回复数据
# 看一下客户端发来的数据
if len(data) != 0:
data = data.decode('utf-8')
print(f'客户端{ip_port[0]} 发送的数据:{data}')
else:
print(f'客户端{ip_port[0]} 关闭了连接')
# 回复数据
data = '你好啊'.encode('utf-8')
tcp_cliect_soket.send(data)
tcp_cliect_soket.close()
tcp_server.close()
多任务的服务端
import socket
import threading
def client_task(client_socket, ip_port):
print('连接进来了')
while True:
# 持续的接收客户端的信息
data = client_socket.recv(1024).decode('utf-8')
if len(data) != 0:
print(f'客户端{ip_port[0]}发来的数据{data}')
else:
print(f'客户端{ip_port[0]}关闭了,下次再见')
break
# 回复
send_data = (data + 'hello').encode('utf-8')
client_socket.send(send_data)
if __name__ == '__main__':
server_tcp = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_tcp.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True)
server_tcp.bind(('', 6666))
server_tcp.listen(128)
while True:
tcp_client_socket, tcp_ip_port = server_tcp.accept()
# 实现多任务
t_client = threading.Thread(target=client_task, args=(tcp_client_socket, tcp_ip_port))
# 设置守护线程
t_client.setDaemon(True)
t_client.start()
server_tcp.close()
class实现
"""
使用类来实现tcp服务器的多任务
"""
import socket
import threading
class SockerServer(object):
def __init__(self, port):
self.server_tcp = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.server_tcp.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True)
self.server_tcp.bind(('', port))
self.server_tcp.listen(128)
def start(self):
while True:
tcp_client_socket, tcp_ip_port = self.server_tcp.accept()
# 实现多任务
t_client = threading.Thread(target=self.client_task, args=(tcp_client_socket, tcp_ip_port))
# 设置守护线程
t_client.setDaemon(True)
t_client.start()
server_tcp.close()
def client_task(self, client_socket, ip_port):
print('连接进来了')
while True:
# 持续的接收客户端的信息
data = client_socket.recv(1024).decode('utf-8')
if len(data) != 0:
print(f'客户端{ip_port[0]}发来的数据{data}')
else:
print(f'客户端{ip_port[0]}关闭了,下次再见')
break
# 回复
send_data = (data + 'hello').encode('utf-8')
client_socket.send(send_data)
if __name__ == '__main__':
s = SockerServer(9999)
s.start()
3. 搭建静态的web服务器
"""
静态的web服务器
1.编写一个tcp的服务端程序
2.获取浏览器的http请求报文的数据
3.读取固定的页面数据,把页面的数据组装成http响应报文的数据发送给浏览器群
4.http响应报文数据发送完成以后,关闭服务与客户端的套接字
"""
# 1.导入模块
import socket
# 2. 创建socket对象
static_web_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
static_web_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True)
static_web_socket.bind(('', 4444))
static_web_socket.listen(128)
# 3.接收请求
while True:
client, ip_port = static_web_socket.accept()
print(f'客户端的{ip_port[0]}使用端口{ip_port[1]}连接成功')
# 3.1 接收客户端得请求信息
request_info = client.recv(1024).decode()
print(request_info)
# 4.读取资源内容
with open('static/index.html', 'rb') as file:
file_content = file.read()
# 5.拼接响应报文
response_line = 'HTTP/1.1 200 OK\r\n'
response_head = 'Server: PSWS1.0\r\n'
response_data = (response_line + response_head + '\r\n').encode() + file_content
# 6.发送响应数据
client.send(response_data)
# 7.关闭连接
client.close()
# 8.关闭
static_web_socket.close()
返回指定数据的
import socket
def server_start(port):
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True)
server.bind(('', port))
server.listen(128)
# 接收数据
while True:
client, ip_port = server.accept()
print(f'客户端连接{ip_port[0]}端口为:{ip_port[1]}成功了。。。')
request_info = client.recv(4096).decode()
if len(request_info) == 0:
print('客户端关闭')
client.close()
else:
# 分割请求报文
request_path = request_info.split(' ')[1]
print('request_path:', request_path)
if request_path == '/':
request_path = '/index.html'
try:
print('static'+request_path)
with open('static'+request_path, 'rb') as file:
file_content = file.read()
except Exception as e:
print('异常处理')
response_line = 'HTTP/1.1 404 NOT FOUND\r\n'
response_head = 'Server: PSWS1.1\r\n'
with open('static/error.html', 'rb') as file:
file_content = file.read()
response_data = (response_line + response_head + '\r\n').encode() + file_content
client.send(response_data)
else:
response_line = 'HTTP/1.1 200 OK\r\n'
response_head = 'Server: PSWS1.1\r\n'
response_data = (response_line + response_head + '\r\n').encode()+file_content
client.send(response_data)
finally:
client.close()
server.close()
# 数据的判断
if __name__ == '__main__':
server_start(7777)
进程实现
import socket
import threading
def server_start(port):
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True)
server.bind(('', port))
server.listen(128)
# 接收数据
while True:
client, ip_port = server.accept()
print(f'客户端连接{ip_port[0]}端口为:{ip_port[1]}成功了。。。')
p1 = threading.Thread(target=task, args=(client,))
p1.start()
server.close()
def task(client):
request_info = client.recv(4096).decode()
if len(request_info) == 0:
print('客户端关闭')
client.close()
else:
# 分割请求报文
request_path = request_info.split(' ')[1]
print('request_path:', request_path)
if request_path == '/':
request_path = '/index.html'
try:
print('static'+request_path)
with open('static'+request_path, 'rb') as file:
file_content = file.read()
except Exception as e:
print('异常处理')
response_line = 'HTTP/1.1 404 NOT FOUND\r\n'
response_head = 'Server: PSWS1.1\r\n'
with open('static/error.html', 'rb') as file:
file_content = file.read()
response_data = (response_line + response_head + '\r\n').encode() + file_content
client.send(response_data)
else:
response_line = 'HTTP/1.1 200 OK\r\n'
response_head = 'Server: PSWS1.1\r\n'
response_data = (response_line + response_head + '\r\n').encode()+file_content
client.send(response_data)
finally:
client.close()
if __name__ == '__main__':
server_start(7777)
class:
import socket
import threading
class Server_Web(object):
def __init__(self, port):
self.server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True)
self.server.bind(('', port))
self.server.listen(128)
def start(self):
# 接收数据
while True:
client, ip_port = self.server.accept()
print(f'客户端连接{ip_port[0]}端口为:{ip_port[1]}成功了。。。')
p1 = threading.Thread(target=self.task, args=(client,))
p1.start()
server.close()
def task(self, client):
request_info = client.recv(4096).decode()
if len(request_info) == 0:
print('客户端关闭')
client.close()
else:
# 分割请求报文
request_path = request_info.split(' ')[1]
print('request_path:', request_path)
if request_path == '/':
request_path = '/index.html'
try:
print('static'+request_path)
with open('static'+request_path, 'rb') as file:
file_content = file.read()
except Exception as e:
print('异常处理')
response_line = 'HTTP/1.1 404 NOT FOUND\r\n'
response_head = 'Server: PSWS1.1\r\n'
with open('static/error.html', 'rb') as file:
file_content = file.read()
response_data = (response_line + response_head + '\r\n').encode() + file_content
client.send(response_data)
else:
response_line = 'HTTP/1.1 200 OK\r\n'
response_head = 'Server: PSWS1.1\r\n'
response_data = (response_line + response_head + '\r\n').encode()+file_content
client.send(response_data)
finally:
client.close()
if __name__ == '__main__':
s = Server_Web(8888)
s.start()
利用sys的参数argv实现:
import socket
import threading
import sys
class Server_Web(object):
def __init__(self, port):
self.server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True)
self.server.bind(('', port))
self.server.listen(128)
def start(self):
# 接收数据
while True:
client, ip_port = self.server.accept()
# print(f'客户端连接{ip_port[0]} 端口为:{ip_port[1]}成功了。。。')
p1 = threading.Thread(target=self.task, args=(client,))
p1.start()
server.close()
def task(self, client):
request_info = client.recv(4096).decode()
if len(request_info) == 0:
print('客户端关闭')
client.close()
else:
# 分割请求报文
request_path = request_info.split(' ')[1]
print('request_path:', request_path)
if request_path == '/':
request_path = '/index.html'
try:
print('static'+request_path)
with open('static'+request_path, 'rb') as file:
file_content = file.read()
except Exception as e:
print('异常处理')
response_line = 'HTTP/1.1 404 NOT FOUND\r\n'
response_head = 'Server: PSWS1.1\r\n'
with open('static/error.html', 'rb') as file:
file_content = file.read()
response_data = (response_line + response_head + '\r\n').encode() + file_content
client.send(response_data)
else:
response_line = 'HTTP/1.1 200 OK\r\n'
response_head = 'Server: PSWS1.1\r\n'
response_data = (response_line + response_head + '\r\n').encode()+file_content
client.send(response_data)
finally:
client.close()
if __name__ == '__main__':
# 需要在服务器下运行
if len(sys.argv) != 2:
print('pytonh3 xxx.py 端口号')
exit(1)
if sys.argv[1].isdigit():
s = Server_Web(8888)
s.start()
else:
print('pytonh3 xxx.py 端口号')