socket(简称 套接字) 是进程间通信的一种方式,它与其他进程间通信的一个主要不同是:
它能实现不同主机间的进程间通信,我们网络上各种各样的服务大多都是基于
Socket 来完成通信的
在 Python 中 使用 socket 模块的函数 socket 就可以完成:
import socket socket.socket(AddressFamily, Type)
说明:
函数 socket.socket 创建一个 socket,该函数带有两个参数:
· Address Family:可以选择 AF_INET(用于 Internet 进程间通信) 或者
AF_UNIX(用于同一台机器进程间通信),实际工作中常用 AF_INET
· Type:套接字类型,可以是 SOCK_STREAM(流式套接字,主要用于 TCP 协议)或者 SOCK_DGRAM(数据报套接字,主要用于 UDP 协议)创建一个 tcp socket(tcp 套接字)
import socket
# 创建 tcp 的套接字
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# ...这里是使用套接字的功能(省略)...
# 不用的时候,关闭套接字s.close()
创建一个 udp socket(udp 套接字)
import socket
# 创建 udp 的套接字
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
# ...这里是使用套接字的功能(省略)...
# 不用的时候,关闭套接字s.close()
创建一个基于 udp 的网络程序流程很简单,具体步骤如下:
import socket
client=socket.socket(socket.AF_INET,socket.SOCK_DGRAM) dest_addr=('192.168.5.7',2000) #client.sendto(b'hello',dest_addr)
client.sendto('howare'.encode('utf8'),dest_addr) #放汉字还是不放都行
data,_=client.recvfrom(100) print(data.decode('utf8')) client.close() #关闭时端口会释放
出错信息:
bind 使用,如果端口被占用
OSError: [Errno 98] Address already in use
当 UDP recvfrom 内部要接的大小,少于发送的字节数,windows 报错,Linux 是不会报错,没有拿的数据直接丢弃。
sendto 和 recvfrom,次数完全对等
说明:
· 每重新运行一次网络程序,上图中红圈中的数字,不一样的原因在于,这个数
字标识这个网络程序,当重新运行时,如果没有确定到底用哪个,系统默认会随机分配
· 记住一点:这个网络程序在运行的过程中,这个就唯一标识这个程序,所以如
果其他电脑上的网络程序如果想要向此程序发送数据,那么就需要向这个数字
(即端口)标识的程序发送即可
<1>. 绑定信息
一般情况下,在一台电脑上运行的网络程序有很多,为了不与其他的网络程序占用
同一个端口号,往往在编程中,udp 的端口号一般不绑定
但是如果需要做成一个服务器端的程序的话,是需要绑定的,想想看这又是为什么
呢?
如果报警电话每天都在变,想必世界就会乱了,所以一般服务性的程序,往往需要
一个固定的端口号,这就是所谓的端口绑定
#coding=utf-8
from socket import *
# 1. 创建套接字
udp_socket = socket(AF_INET, SOCK_DGRAM)
# 2. 绑定本地的相关信息,如果一个网络程序不绑定,则系统会随机分配
local_addr = ('', 7788) # ip 地址和端口号,ip 一般不用写,表示本机的任何一个 ip
udp_socket.bind(local_addr)
# 3. 等待接收对方发送的数据
recv_data = udp_socket.recvfrom(1024) # 1024 表示本次接收的最大字节数
# 4. 显示接收到的数据print(recv_data[0].decode('utf8'))
# 5. 关闭套接字udp_socket.close()
运行:
howare
(‘192.168.3.28’, 51404)
· 一个 udp 网络程序,可以不绑定,此时操作系统会随机进行分配一个端口,如果重新运行此程序端口可能会发生变化· 一个 udp 网络程序,也可以绑定信息(ip 地址,端口号),如果绑定功,那么操作系统用这个端口号来进行区别收到的网络数据是否是此进程的端口占用怎么办?
这里讲解 kill 命令
ps -elf 查看进程
kill -9 进程 id
def main():
#创建套接字
udp_socket=socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
udp_socket.bind(("0.0.0.0",8082 ))
while True:
# 3. 选择功能print("="*30) print("1:发送消息") print("2:接收消息") print("="*30)
op_num = input("请输入要操作的功能序号:")
# 4. 根据选择调用相应的函数
if op_num == "1":
send_msg(udp_socket)
elif op_num == "2":
recv_msg(udp_socket)
else:
print("输入有误,请重新输入...")
if __name__ == '__main__':
main()
~