赞
踩
Socket又称"套接字",应用程序通常通过"套接字"向网络发出请求或者应答网络请求,使主机间或者一台计算机上的进程间可以通讯。
Python 中,我们用 socket() 函数来创建套接字,语法格式如下:
socket.socket([family[, type[, proto]]])
SOCK_STREAM(UDP方式)或SOCK_DGRAM(TCP方式)UDP(User Datagram Protocol,用户数据报协议)是一种无连接的协议,用于在IP主机和应用程序之间发送数据报。与TCP(Transmission Control Protocol,传输控制协议)不同,UDP不提供数据报的排序、重传或确认机制,因此被称为不可靠的协议。
1、向指定主机和端口发送消息
2、指定接收消息的端口并接收消息、
3、使用多线程方法一直接收消息
1、创建UDP套接字
udp_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
2、绑定接收端口
udp_socket.bind(("", 8888))
3、发送消息
因为计算机间的通信是二进制的,需要使用encode()方法将发送的数据转为二进制
udp_socket.sendto(send_str.encode(), (ip_str, port))
4、接收消息
recvfrom的返回值是一个元组,接收到的消息分为两部分,一部分是消息内容,一部分是发送方的ip和端口。同样的接收到的消息需要使用decode()方法解码
data = udp_socket.recvfrom(1024)
- import socket
- import threading
- """UDP聊天器"""
-
-
- def Socket_Sento(udp_socket):
- ip_str = input("请输入对方的ip地址:")
- port = int(input("请输入对方的端口号:"))
- send_str = input("请输入要发送的内容:")
- udp_socket.sendto(send_str.encode(), (ip_str, port))
-
-
- def Socket_Recvfrom(udp_socket):
- while True:
- data = udp_socket.recvfrom(1024)
- print("来自主机:%s:%d发来的消息:%s\n" % (data[1][0], data[1][1], data[0].decode("gbk")))
-
-
- def main():
- udp_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
- udp_socket.bind(("", 8888))
- t1 = threading.Thread(target=Socket_Recvfrom, args=(udp_socket,), daemon=True)
- t1.start()
- while True:
- print("\n\n***************************")
- print("****** 1、发送信息 *******")
- print("****** 2、退出系统 *******")
- print("***************************")
- num = input("请选择功能序号\n")
- if num == "1":
- Socket_Sento(udp_socket)
- elif num == "2":
- break
- else:
- print("输入错误")
- udp_socket.close()
-
-
- if __name__ == "__main__":
- main()

TCP(Transmission Control Protocol,传输控制协议)是一种面向连接的、可靠的、基于字节流的传输层通信协议。
使用TCP时与UDP不同,需要先建立连接
tcp_client_socket.connect(("192.168.56.1",8080))
- import socket
- # 创建套接字
- tcp_client_socket=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
- # 建立连接
- tcp_client_socket.connect(("192.168.56.1",8080))
- # 发送数据
- tcp_client_socket.send("约吗".encode())
- # 接收数据
- print(tcp_client_socket.recv(1024).decode("gbk"))
-
- tcp_client_socket.close()
当TCP作为服务端的时候需要设置地址重用、绑定端口、设置监听
tcp_server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True)
tcp_server_socket.bind(("", 8080))
tcp_server_socket.listen(128)
- import socket
- import threading
- """多线程TCP服务框架"""
-
- def recv_msg(new_socket, client_port):
- while True:
- recv_data = new_socket.recv(1024)
- if recv_data:
- print("来自[%s]发送的数据:%s" % (client_port, recv_data.decode("gbk")))
- else:
- print("客户端已断开连接")
- break
-
-
- tcp_server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
- # 设置地址重用
- tcp_server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True)
- # 绑定端口
- tcp_server_socket.bind(("", 8080))
- # 设置监听
- tcp_server_socket.listen(128)
- # 循环实现多个客户端连接
- while True:
- new_socket, client_port = tcp_server_socket.accept()
- print("与%s连接成功" % str(client_port))
- recv_thread = threading.Thread(target=recv_msg, args=(new_socket, client_port), daemon=True)
- recv_thread.start()
-
- # tcp_server_socket.close()

浏览器的请求分为get请求和post请求
get请求的请求协议包含请求行、请求头、请求空行
post请求的请求协议包含请求行、请求头、请求空行、请求内容
- import socket
- # 创建套接字
- tcp_client_socket=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
-
- # 建立连接
- tcp_client_socket.connect(("127.0.0.1",8080))
-
- # 拼接请求协议
- # 请求行
- request_line="GET / HTTP/1.1\r\n"
- #请求头
- request_header="Host:www.baidu.com\r\n"
- #请求空行
- requset_blank="\r\n"
- request_data=request_line+request_header+requset_blank
- #发送请求协议
- tcp_client_socket.send(request_data.encode())
- #接收服务器响应内容
-
- respon_data=tcp_client_socket.recv(4096).decode()
- html_data=respon_data[respon_data.find("\r\n\r\n")+4:]
- print(html_data)
- # 保存内容
-
- with open("D:\\PycharmProjects\\TextProject\\Text_TCP_Web\\index.html","w") as file:
- file.write(html_data)
-
- #关闭连接
- tcp_client_socket.close()

首先需要解码请求协议,将接收到的请求解码拆分得到要请求的内容
然后创建响应协议:响应行、响应头、响应空行、响应主体,最后拼接发送给请求端
- import socket
-
-
- def request_headler(new_client_socket, ip_port):
- request_data = new_client_socket.recv(1024).decode()
- # print(request_data)
- # 接收客户端浏览器发送的请求
- # 判断协议是否为空
- if not request_data:
- print("%s用户已下线" % str(ip_port))
- new_client_socket.close()
- return
- # 根据客户端浏览器请求的资源路径,返回请求资源
- # 把请求协议解码,得到请求报文的字符串
- # 得到请求行
- # 查找第一个\r\n出现得位置
- # 使用切片获取请求行
- requst_line = request_data[0:request_data.find("\r\n")]
- # 按空格分割创建数组
- requst_line_list = requst_line.split(" ")
- # 获取到指定文件
- file_path = requst_line_list[1]
- # 如果没有指定访问的文件就返回默认首页
- if file_path == "/":
- file_path = "index.html"
- print("[%s]用户请求了%s资源" % (str(ip_port), file_path))
- # 拼接响应的报文
- # 响应行
- respon_line = "HTTP/1.1 200 OK\r\n"
- # 响应头
- respon_header = "Server:Python\r\n"
- # 响应空行
- respon_blank = "\r\n"
- # 响应主体
- # respon_body = "Hello Wolrd"
- # 返回指定页面
- try:
- with open("..\\static\\" + file_path, "rb") as file:
- respon_body = file.read()
- except Exception as e:
- respon_line = "HTTP/1.1 404 Not Found\r\r"
- respon_body = "Error! (%s)" % e
- respon_body = respon_body.encode()
- # 发送响应报文
- respon_data = (respon_line + respon_header + respon_blank).encode() + respon_body
- new_client_socket.send(respon_data)
-
-
- def main():
- # 创建套接字
- tcp_sderver_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
- # 设置端口重用、
- tcp_sderver_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True)
- # 绑定端口
- tcp_sderver_socket.bind(("", 8080))
- # 设置监听,让套接字由主动变为被动接收
- tcp_sderver_socket.listen(128)
- # 接受客户端的请求 定义函数request_handler()
- while True:
- new_client_socket, ip_port = tcp_sderver_socket.accept()
- print("新用户%s来了" % str(ip_port))
- request_headler(new_client_socket, ip_port)
- # 关闭操作
- tcp_sderver_socket.close()
-
-
- if __name__ == "__main__":
- main()

- import socket
- clinent_socket=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
- clinent_socket.connect(("192.168.56.1",8080))
- file_name=input("请输入要下载的文件名:")
- clinent_socket.send(file_name.encode())
-
- with open("C:\\Users\\Administrator\\Desktop\\copy\\"+file_name, "wb") as source_file:
- while True:
- file_data = clinent_socket.recv(1024)
- if file_data:
- source_file.write(file_data)
- else:
- break
- clinent_socket.close()
-
- import socket
- server_socket=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
- server_socket.bind(("",8080))
- server_socket.listen(128)
- while True:
- new_server_socket,clinet_port=server_socket.accept()
- print("客户端[%s]已连接"%str(clinet_port))
- clinet_data=new_server_socket.recv(1024)
- try:
- with open("C:\\Users\\Administrator\\Desktop\\"+clinet_data.decode(),"rb") as server_file:
- while True:
- file_date=server_file.read(1024)
- if file_date:
- new_server_socket.send(file_date)
- else:
- print("文件传输完成")
- break
- except Exception as e:
- print("文件%s传输失败"%clinet_data.decode())
- new_server_socket.close()
-
- server_socket.close()

Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。