udp发送完消息后要关闭端口描述符

在UDP通信中,如果不关闭发送消息后的端口描述符,可能导致第二次尝试通信时无法正常接收数据,甚至线程被挂住。正确做法是在发送完毕后记得关闭端口描述符。
int get_osd_oob_list(struct osd_node onode, struct list_head *head)
{
	printf("\nEntering %s ", __func__);
	char message[4096];
	char oob_receive_buf[8192];
	int ret, m_type, valid_len;
	int failure_time = 0;
	int socket_descriptor;
	struct sockaddr_in sin;
	int sin_len;
	int port = OSD_RECEIVE_RESULT_PORT;
	int is_cur_osd = (onode.osd_no == current_osd_no) ? 1:0;
	CACHE_INFO("This time being processed osd_node is: no:%d and name %s and current restarted osdno:%d",\
		onode.osd_no, onode.osd_address, current_osd_no);
	CACHE_INFO("+++++++++In line%d and is_cur_osd :%d", __LINE__, is_cur_osd);
	if(onode.osd_no == current_osd_no)
		is_cur_osd = 1;
	CACHE_INFO("++++++++++++++++IN line%d and is_cur_osd :%d", __LINE__, is_cur_osd);
	memset(&sin, 0, sizeof(sin));
	sin.sin_family=AF_INET;
	sin.sin_addr.s_addr=htonl(INADDR_ANY);
	sin.sin_port=htons(port);
	sin_len=sizeof(sin);
	socket_descriptor=socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP);
	bind(socket_descriptor,(struct sockaddr *)&sin,sizeof(sin));
	
	*(uint32_t *) &message[0] = OOB_SCAN;
	memcpy(&message[4], current_osd_ip, 20); 
	send_osd_message(onode.osd_address, OSD_RECEIVE_CMD_PORT, message, 24);
	printf("\nIn %s and line:%d and read oob info cmd is sent to osd:%s", __func__, __LINE__, onode.osd_address);
	
	while(1){
		if(recvfrom(socket_descriptor,oob_receive_buf, sizeof(oob_receive_buf),0,(struct sockaddr *)&sin,&sin_len)){
			m_type = get_ntohl_be(&oob_receive_buf[0]);
			if(m_type!=OOB_DATA){
				CACHE_DEBUG("Invalid data because the data type is not OOB_DATA...");
				failure_time++;
				if(failure_time > 2)
					break;
				else
					continue;
			}
			valid_len = get_ntohl_be(&oob_receive_buf[4]);
			if(!valid_len){
				CACHE_INFO("No more valid oob info on node %s and goto next step... ", onode.osd_address);
				break;
			}
			CACHE_INFO("Received oob info len:%d", valid_len);
			if(valid_len % OOB_LEN != 0)
				CACHE_DEBUG("Something is wrong with the oob data len...");
			ret = oob_data_process(oob_receive_buf+8, valid_len, head, is_cur_osd);
		}//if
	}
	
	close(socket_descriptor);
	printf("\nLeaving %s ...\n\n", __func__);
	return 0;
}

 

按如下调用上述函数,在忘记close(socket_descriptor);的时候,第二次进入上述函数,无法正常接收数据,线程挂住!

for(i=0; i< related_osd_table->osd_count; i++){
	printf("\nTo get osd oob list %d", i);
	ret = get_osd_oob_list(related_osd_table->osd[i], &osd_oobinfo_list[i]);
}

<think> 我们参考了引用内容,其中提到了两种方法: 1. 使用重定向到/dev/udp/来实现UDP发送(引用[1]) 2. 使用nc(netcat)命令(引用[2]) 根据用户需求,我们需要使用shell脚本给某个端口发送UDP消息。下面将介绍两种方法。 方法一:使用重定向到/dev/udp/ 在支持/dev/udp/的shell(如bash)中,我们可以通过以下步骤: 步骤1:使用exec打开一个文件描述符(例如8)连接到指定的UDP地址和端口。 步骤2:通过该文件描述符发送数据。 步骤3:关闭文件描述符。 示例脚本(发送一条消息): #!/bin/bash # 定义目标IP和端口 IP="10.0.2.15" PORT="12345" # 打开文件描述符8用于UDP通信 exec 8<>/dev/udp/${IP}/${PORT} # 发送消息(注意:消息末尾需要换行,否则可能不会立即发送) echo "Hello UDP Server" >&8 # 关闭文件描述符 exec 8>&- 注意:这种方法在发送后不会等待接收回复。另外,如果目标端口不可达,可能会收到ICMP错误(如引用[1]中所示),但脚本不会处理。 方法二:使用nc(netcat)命令 nc命令是一个功能强大的网络工具,可以用于发送UDP数据。 示例命令: echo "Hello" | nc -u -w1 10.0.2.15 12345 参数说明: -u: 指定UDP协议 -w1: 设置超时时间(这里设置为1秒) 在脚本中,我们可以这样写: #!/bin/bash IP="10.0.2.15" PORT="12345" echo "Hello UDP Server" | nc -u -w1 $IP $PORT 注意:nc命令在某些系统中可能没有安装,需要先安装。另外,nc命令在发送后可以等待接收回复(但这里我们只是发送,不接收)。 两种方法的比较: 1. 使用/dev/udp/是bash内置的功能,不需要额外工具,但仅限于支持/dev/udp/的shell(如bash,但dash等不支持)。 2. 使用nc命令更通用,但需要安装netcat。 根据实际情况选择合适的方法。 另外,如果需要发送二进制数据或更复杂的数据,可以使用其他工具(如socat)或者使用编程语言(如Python),但用户要求使用shell脚本。 因此,我们提供以上两种shell脚本方法。 注意:如果发送的数据量较大,或者需要连续发送多条,可能需要考虑使用循环和适当的延迟。 示例:连续发送10条消息(使用nc) #!/bin/bash IP="10.0.2.15" PORT="12345" for i in {1..10}; do echo "Message $i" | nc -u -w1 $IP $PORT sleep 1 done 使用重定向的方式也可以连续发送,但注意不要频繁打开关闭文件描述符(可以在循环外打开,循环内发送,最后关闭): #!/bin/bash IP="10.0.2.15" PORT="12345" exec 8<>/dev/udp/${IP}/${PORT} for i in {1..10}; do echo "Message $i" >&8 sleep 1 done exec 8>&- 以上脚本在循环内发送10条消息,每条间隔1秒。 请根据实际需求调整。 注意:UDP是无连接的,因此每条消息都是独立的。如果目标服务没有启动,发送UDP报文可能会被目标主机拒绝(通过ICMP端口不可达),但发送端脚本不会知道(除非我们监听ICMP错误,但shell脚本中处理ICMP错误比较复杂)。 因此,如果需要确认消息是否送达,通常需要在应用层设计确认机制。 最后,引用[1]中提到了使用重定向发送UDP报文的方法,引用[2]中则使用了nc来检测UDP端口。我们综合这两种方法给出了发送UDP消息的两种方式。 希望这些方法能帮助用户解决问题。 </think>在 Shell 脚本中发送 UDP 消息主要有以下两种方法,均基于系统内置功能或常用工具: ### 方法一:使用 `/dev/udp/` 伪设备(Bash 内置) ```bash #!/bin/bash # 定义目标地址和端口 DEST_IP="10.0.2.15" # 替换为目标IP DEST_PORT="12345" # 替换为目标端口 # 打开UDP套接字(文件描述符8) exec 8<>/dev/udp/$DEST_IP/$DEST_PORT # 发送消息 echo "Hello UDP Server" >&8 # 发送文本消息 # 关闭连接 exec 8>&- ``` **原理说明**: 通过文件描述符重定向到伪设备 `/dev/udp/`,直接建立 UDP Socket 连接。每条 `echo` 命令发送的内容会被封装成独立 UDP 数据包[^1]。 --- ### 方法二:使用 `nc` (netcat) 命令 ```bash #!/bin/bash DEST_IP="10.0.2.15" DEST_PORT="12345" # 单次发送 echo "Test message" | nc -u -w1 $DEST_IP $DEST_PORT # 持续发送(每秒1条) for i in {1..5}; do echo "Packet $i" | nc -u -w1 $DEST_IP $DEST_PORT sleep 1 done ``` **参数说明**: - `-u`:使用 UDP 协议 - `-w1`:设置超时时间(1秒) - 支持二进制数据:`echo -e "\x01\x02" | nc ...` --- ### 方法对比 | 特性 | `/dev/udp` 方式 | `nc` 方式 | |--------------|----------------------------------|-------------------------------| | 依赖 | Bash 内置(需 Bash 4+) | 需安装 netcat 包 | | 二进制支持 | 是 (`echo -en "\x01" >&8`) | 是 | | 超时控制 | 无内置超时 | 通过 `-w` 参数设置 | | 多系统兼容 | 仅支持 Linux/Bash | 跨平台(BSD/Linux/macOS) | > ⚠️ **注意事项**: > 1. UDP 是无连接协议,发送后不会确认对方是否收到 > 2. 目标端口未监听时可能触发 ICMP 不可达错误(可通过 `tcpdump` 抓包验证)[^1] > 3. 防火墙设置可能阻止 UDP 通信
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值