Socket简介
不同电脑上的进程之间如何通信
首先解决的问题是如何唯一标识一个进程,否则通信无从谈起。
在一台电脑上可以通过进程号(PID) 来唯一标识一个进程,但是在网络上这是行不通的。
其实TCP/IP协议族已经帮我们解决了这个问题,网络层的“ip地址”可以标识唯一网络中的主机,而传输层的“协议+端口”可以唯一标识主机中的应用程序(进程)。
这样利用ip地址 + 协议 + 端口 就可以标识网络的进程了,网络中的进程通信就可以利用这个标志与其他进程进行交互
注意:
- “进程”:运行的程序以及运行时用到的资源这个整体称之为进程
- “进程间通信”:运行的程序之间的数据共享
什么是Socket
Socket(简称:套接字)是进程间通信的一种方式,它与其他进程间通信的一个主要不同是:
它能实现不同主机间的进程通信,我们网络上各种各样的服务大多同时基于Socket来完成通信的,例如我们每天浏览网页,QQ聊天,收发Email等等。
创建Socket
在Python中使用socket模块中的socket方法就可以完成
socket.socket(Family, Type)
简述:
- socket类创建的对象,该对象带有两个默认参数:
family:
可以选择AF_INET(用于internet进程间通信) 或者AF_UNIX(用于 同一台机器进程间通信), 实际工作中常用AF_INET
type:
套接字类型,可以是SOCKET_ STREAM(流式套接字, 主要用于TCP协议)或者SOCK_ DGRAM(数据报套接字,主要用于UDP协议)
发送UDP数据
import socket
def main():
# 创建一个udp的套接字
udp_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
# 循环发送,并支持exit指令退出程序
while True:
##### 接收键盘输入信息
content = input('请输入内容: ')
if content == 'exit':
break
# udp_socket.sendto(数据, 目的IP与Port)
udp_socket.sendto(content.encode('utf-8'), ('10.0.0.1', 8080))
# 关闭套接字
udp_socket.close()
if __name__ == '__main__':
main()
接受UDP数据
如果程序要接收数据,必须固定端口
代码如下:
from socket import *
def main():
# 1. 创建udp套接字
udp_socket = socket(AF_INET, SOCK_DGRAM)
# 2. 添加本地信息
local_address = ('', 7878) 必须是本机的ip port
udp_socket.bind(local_address)
# 3. 接收数据
receive_data = udp_socket.recvfrom(1024) 数据bytes大小
接收的数据是一个tuple类型,包含发送方的数据,ip,port(b’data’, (‘192.168.0.0’ , port))
receive_msg = receive_data[0].decode('gbk') # 存储接收的信息
send_address = receive_data[1] # 存储发送方的地址
# 4. 打印数据
print('%s:%s' % (str(send_address), receive_msg))
# 5. 关闭套接字
udp_socket.close()
if __name__ == '__main__':
main()
绑定端口
当网络程序开始运行,进行收发数据,未进行固定端口,系统则随机分配一个端口,结束进程则释放该端口。
一般接收方需事先绑定端口
注意:UDP中端口不能被占用
常见问题
recvfrom 在数据没有到来是会怎样?
调用recvfrom之后,数据未到
它会处于堵塞状态
没有调用recvfrom之前,数据已到
数据首先进入操作系统缓存区,再调用recvfrom找到数据
注意:易导致操作系统内存占满
socket是 全双工?
套接字是一个,可以同时 收发数据的
飞秋通信用的是2425端口,那么qq呢?qq怎样通信?
扩展知识
单工:收音机此类,无法发送数据,只能接收数据
半双工:对讲机,可以收发数据,但不能同时收发
全双工:可以同时收发数据