目录
目录
1.socket简介
2.创建socket
2.1创建UDPSocket
2.2创建TCPSocket
3.使用UDPSocket发送数据并接收
4.使用UDPSocket发送广播
5.UDPSocket聊天器 (多线程实现消息的收发功能)
6.使用TCPSocket建立客户端
7.使用TCPSocket建立服务端
1.socket简介
socket(简称:套接字),是支持TCP和UDP(网络传输方式)网络通信的基本操作单元,可以看做是不同主机之间的进程进行双向通信的端点,简单的说就是通信的两方的一种约定,用套接字中的相关函数来完成通信过程。
它能实现不同主机间的进程间通信,我们网络上各种各样的服务大多都是基于socket来完成通信的,例如浏览的网页、qq聊天、收发email等等。
2.创建socket
socket起源于Unix,而Unix/Linux基本哲学之一就是“一切皆文件”,对于文件用打开、读写、关闭模式来操作。socket就是该模式的一个实现,socket即是一种特殊的文件,一些socket类就是对其进行的操作(读写IO、打开、关闭)
在Python中使用socket模块的socket类来完成:
import socketsocket.socket(AddressFamily, Type)
说明:
1. 参数:AddressFamily(地址簇)
socket.AF_INET IPv4 (默认)
socket.AF_INET6 IPv6
socket.AF_UNIX 只能够用于单一的Unix系统进程通信
2.参数:Type(类型)
socket.SOCK_STREAM 流式socket,for TCP(默认)
socket.SOCK_DGRAM 数据报式socket,for UDP
2.1创建UDPSocket
import socket# 使用IPv4 UDP方式来创建套接字udp_socket = socket.socket(socket.AF_INET,socket.SOCK_DGRAM) # 参数socket.AF_INET表示使用IPv4,参数socket.SOCK_DGRAM表示使用UDP# 省略数据传递过程# 关闭套接字udp_socket.close()
2.2创建TCPSocket
import socket# 使用IPv4 TCP方式来创建套接字tcp_socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM) # 参数socket.AF_INET表示使用IPv4,参数socket.SOCK_STREAM表示使用TCP# 省略数据传递过程# 关闭套接字tcp_socket.close()
3.使用UDPSocket发送数据并接收
核心方法:
socket.sendto
sendto方法的参数:
1.要发送的二进制数据 (使用.encode()方法可以将字符串转为二进制)
2.接收者的ip地址和端口号 (元组类型:("127.0.0.1", 8080))
import socket# 使用IPv4 UDP方式来创建套接字udp_socket = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)#2.绑定一个本地信息localaddr = ("192.168.68.196",8081)udp_socket.bind(localaddr)# 发送数据udp_socket.sendto("hello".encode(),("192.168.68.196",8080))# 关闭套接字udp_socket.close()
接收数据(两种方式):
方式一:通过网络调试助手接收(下载地址:NetAssist.exe下载)
对于接收到的中文是乱码的问题:
可能是由于encode()方法默认使用UTF-8的编码方式
.encode()
将其改为gb2312编码方式:
.encode("gb2312")
如下图标注部分为修改编码方式前后的对比:
方式二:通过python代码制作一个接收端
import socketdef main(): #1.创建套接字 udp_socket = socket.socket(socket.AF_INET,socket.SOCK_DGRAM) #2.绑定一个本地信息 localaddr = ("192.168.68.196",8080) udp_socket.bind(localaddr) #3.接收数据 while True: recv_data = udp_socket.recvfrom(1024) #1024表示每次接收1024字节 recv_msg = recv_data[0] #存储接收到的数据 send_addr = recv_data[1]#存储发送方的地址信息 #4.打印接收到的数据 # print(recv_data) print("%s:%s" % (str(send_addr),recv_msg.decode("gb2312")) ) #5.关闭套接字 udp_socket.close()if __name__ == "__main__": main()
4.使用UDPSocket发送广播
广播地址(Broadcast Address)是专门用于同时向网络中所有工作站进行发送的一个地址。在使用TCP/IP 协议的网络中,主机标识段host ID 为全1 的IP 地址为广播地址,广播的分组传送给host ID段所涉及的所有计算机。例如,对于10.1.1.0 (255.0.0.0 )网段,其广播地址为10.255.255.255 (255 即为二进制的11111111 ),当发出一个目的地址为10.255.255.255 的分组(封包)时,它将被分发给该网段上的所有计算机。
import socket# 使用IPv4 UDP方式来创建套接字udp_socket = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)#2.绑定一个本地信息localaddr = ("192.168.68.196",8081)udp_socket.bind(localaddr)# 设置允许发送广播udp_socket.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, True)# 发送信息udp_socket.sendto("大家好,我宣布个事儿".encode("gb2312"), ("255.255.255.255", 8080))# 关闭套接字udp_socket.close()
运行结果:(此时处于同一网段,端口为8080的客户端应该都能接收到广播信息)
5.UDPSocket聊天器 (多线程实现消息的收发功能)
实现效果:
python UDPSocket聊天器 (多线程实现消息的收发功能)
代码:
import socketfrom threading import Thread,Lockdef send_msg(udp_socket): """发送信息的函数""" while True: input_msg = input("请输入聊天内容:\n") # 用户输入一些信息 udp_socket.sendto(input_msg.encode("gb2312"), ("192.168.68.196", 8081))def recv_msg(udp_socket): """接收信息的函数""" while True: recv_data, tuple_ip_port = udp_socket.recvfrom(1024) recv_text = recv_data.decode("gb2312") print("接受到[%s]的信息:%s" % (str(tuple_ip_port), recv_text))def main(): # 创建套接字 udp_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) # 绑定端口 udp_socket.bind(("", 8080)) # 接收信息 t1 = Thread(target=recv_msg, args=(udp_socket,)) t1.start() # 发送信息 t2 = Thread(target=send_msg, args=(udp_socket,)) t2.start() # # 关闭套接字 # udp_socket.close()if __name__ == '__main__': main()
6.使用TCPSocket建立客户端
import socket# 创建套接字tcp_client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)# 建立连接tcp_client_socket.connect(("192.168.68.196", 8081))# 发送数据tcp_client_socket.send("你好".encode("gb2312"))# 接收数据recv_data = tcp_client_socket.recv(1024).decode("gb2312")print(recv_data)# 关闭套接字tcp_client_socket.close()
7.使用TCPSocket建立服务端
·能够实现一个客户端发来的多条信息
·能够接收多个客户端连接
import socketfrom threading import Threaddef new_client_connect(new_client_socket, client_ip_port): while True: # 收发数据 recv_data = new_client_socket.recv(1024) if len(recv_data) != 0: recv_text = recv_data.decode("gb2312") print("接收到[%s]的信息:%s" % (str(client_ip_port), recv_text)) else: print("客户端断开连接") break # # 关闭连接 # new_client_socket.close() # 表示断开与当前的客户端的通信def main(): # 创建套接字 tcp_server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # 绑定端口和ip tcp_server_socket.bind(("", 8081)) # 设置套接字为被动监听模式,不能主动发送数据,128为允许接收的最大连接数 tcp_server_socket.listen(128) while True: # 接收客户端连接 new_client_socket, client_ip_port = tcp_server_socket.accept() t1 = Thread(target=new_client_connect, args=(new_client_socket, client_ip_port)) t1.start() # tcp_server_socket.close() # 表示不再接受新客户端的连接,已经连接的可以继续服务if __name__ == '__main__': main()
效果:
python TCPSocket服务器 (多线程实现消息的接收功能)