# -*- coding: utf-8 -*-
import socket
import threading
# 启动往 8172 端口发送数据的服务
def send_data():
# 创建 TCP 套接字
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 绑定 IP 地址和端口号
s.bind(('127.0.0.1', 8172))
# 开始监听连接
s.listen()
print('Send data server started.')
# 等待连接
conn, addr = s.accept()
print('Connected by', addr)
# 发送数据
conn.sendall(b'Hello, world!')
# 关闭连接
conn.close()
# 启动从 8172 端口获取数据的服务
def get_data():
# 创建 TCP 套接字
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 连接到目标主机和端口号
s.connect(('127.0.0.1', 8172))
print('Get data server started.')
# 接收数据
data = s.recv(1024)
print('Received', data.decode())
# 关闭连接
s.close()
# 启动两个服务
t1 = threading.Thread(target=send_data)
t2 = threading.Thread(target=get_data)
t1.start()
#t2.start()
如上,如果只发送数据,启动服务
python .\test\bci2000\udp_server.py
会一直hang在下面这行代码
conn, addr = s.accept()
服务会一直等待接收程序的连接
这个时候如果在其他terminal里面测试8172端口的连通性,会接收到发送服务的数据,发送服务也会继续向下执行
如果注释掉发送服务的线程开启,打开接受数据的线程,执行文件之后会报错
因为这个端口号没有被开启
还有一个知识点,如果把tcp套接字换成udp套接字,程序走到listen这里会报错
因为UDP协议是面向无连接的,因此UDP套接字是不能像TCP套接字那样使用
listen()方法进行监听的。listen()方法是用于TCP套接字的,它使得TCP套接字可以开始监听来自客户端的连接请求,并准备接受这些连接。但是,UDP套接字并不需要进行连接的建立,因此也就没有必要使用listen()方法进行监听。
相反,UDP套接字通常使用bind()方法将套接字绑定到一个固定的IP地址和端口号,以便可以从该地址和端口接收数据报。然后,可以使用recvfrom()方法从套接字接收数据报,或者使用sendto()方法向指定的目标地址和端口发送数据报。
因此,如果您需要使用UDP套接字来接收或发送数据报,您只需要使用bind()方法将套接字绑定到合适的地址和端口即可。但是请注意,由于UDP是无连接的,因此您将需要在您的代码中自己处理数据报的排序、重传、丢失等问题。
使用命令查看目前端口使用情况,会发现4个部分,有协议,本地地址,外部地址,状态,TCP连接,连接状态包括"ESTABLISHED"、"SYN_SENT"、"SYN_RECEIVED"、"FIN_WAIT_1"、"FIN_WAIT_2"、"TIME_WAIT"、"CLOSE_WAIT"、"LAST_ACK"和"CLOSED"等状态。对于UDP连接,不会有连接状态这一栏。,所以千万不要做在过滤udp端口的同时还过滤状态栏的傻事,会一无所获
在同一台计算机上,同一个UDP端口只能被一个进程占用并监听。如果尝试在同一端口上启动另一个进程来监听UDP流量,那么会出现端口冲突的错误。因此,同一UDP端口只能被一个进程监听,如果需要多个进程监听同一端口,可以使用多播(multicast)或广播(broadcast)等技术。
在工作中写了一个脚本监听4001端口
然后启动bci2000,因为其中有个程序需要监听4001端口,所以启动会报错