用于搜索网络设备,UDP组播,大概几十台,算100台吧,机器收到后马上回复身份及网络配置等信息,
设备少时没问题,两次发送之间有间隔也没问题,设备多了,会搜索不全。
缓冲区太小的问题我已解决。
1/一师傅说是消息同步问题(导致计数变量不对),我始终不能理解,难道不是每个设备发消息来后,存入缓冲区,慢慢挨个触发消息并挨个处理么?
2/难道是每个机器回复后都触发一个消息同时新建一个线程(即消息响应函数OnReceive)同时处理?
3/怎么解决这个问题?
网上类似问题,没找到答案:
“很菜 ,没做过网络方面程序,请教个问题 先谢谢。
一个主机,10个左右设备,UDP协议,设备5分钟左右(时间间隔随机)向主机发数据,主机处理数据然后回应,数据量很小(20字节)。
参照网上的资料写了段 基于MFC的UDP程序:
创建一个CAsyncSocket子类对象,然后通过Create函数设定端口号和协议类型为 SOCK_DGRAM,通过SendTo函数发送数据,通过ReceiveFrom接收数据。接两个设备通信正常。
问题:若两个以上设备同时向主机发数据包,主机还能正常接收、回应吗?
若不能,该怎样改程序?
http://topic.csdn.net/u/20110309/23/5cd8f1f9-4d87-406a-b9c3-5041871c3400.html
”
20 个解决方案
#1
什么意思啊,没人回复,也看不到浏览数。。。。。
各位大侠千万不要不屑于回答我啊,随便说两句,指点迷津啊
各位大侠千万不要不屑于回答我啊,随便说两句,指点迷津啊
#2
估计是事件触发问题。
WSAAsyncSelect是边缘触发,要 recvfrom 的错误码为 EWOULDBLOCK 才会产生下个FD_READ。
可能lz收到消息后只recvfrom一次。
不是,常规使用方式下,消息还是传递到界面线程,不会另建线程,也不会并行处理。
WSAAsyncSelect是边缘触发,要 recvfrom 的错误码为 EWOULDBLOCK 才会产生下个FD_READ。
可能lz收到消息后只recvfrom一次。
不是,常规使用方式下,消息还是传递到界面线程,不会另建线程,也不会并行处理。
#3
以下摘自百度百科,按他说 每次只要一次就可以了啊:
对FD_READ,FD_OOB和FD_ACCEPT事件,消息传递是"水平触发"(level-triggered)的.这意味着,若调用了重新通知函数并且相关的事件对该调用仍有效,WSAAsyncSelect()消息就将传给应用程序.这为应用程序提供了事件驱动以及不必考虑在任一时刻到达的数据量的能力.考虑下列序列: (i) Windows Sockets DLL在套接口s上接收100字节的数据并传递一个FD_READ消息. (ii) 应用程序启动recv(s,buffptr,50,0)接收50字节. (iii) 由于仍有数据未读,Windows Sockets DLL发送另一个FD_READ消息. 根据以上语义,应用程序不必在收到FD_READ消息时读进所有可读的数据-对应于每一FD_READ消息进行一次recv()调用是恰当的.如果应用程序为一个FD_READ消息而启动了多个recv()调用,它将接收到多个FD_READ消息.这样的应用程序可能希望在开始recv()调用( 通过不为FD_READ事件置位的WSAAsyncSelect()函数调用)之前关闭FD_READ消息.
#4
recvfrom 是单个工作线程么?
如果是,应该没有问题。
如果是,应该没有问题。
#5
采用UDP就不要用什么其他模型了, 直接bind以后就循环recvfrom就行了...毕竟UDP又不用管理SOCKET
#6
边缘触发.. 搞linux的专业术语啊..
一直对udp无爱。。 100多台. tcp也能做啊. 还能保证完整性. udp内网传输理论是超越tcp的
一直对udp无爱。。 100多台. tcp也能做啊. 还能保证完整性. udp内网传输理论是超越tcp的
#7
另开线程循环recvfrom?这跟消息触发有什么区别?为什么消息触发就丢掉一些?
#8
最好别用CSocket类
#9
我没有用CSocket类
#10
int ret = WSAAsyncSelect(m_sockRecv, m_hWnd, WM_MULTIPOINTEVENT,
FD_WRITE | FD_READ | FD_CONNECT);
if(ret == SOCKET_ERROR)
{
TRACE("ERRROR : WSAAsyncSelect - %d .\n", WSAGetLastError());
}
…………………………
case FD_READ:
MsgNum++;
WaitForSingleObject(m_hEvent, INFINITE);
TRACE("MsgNum : %d ", MsgNum);
if((ret = recvfrom(sockfd, buff, BUFFER_SIZE, 0, (sockaddr *) & from, & salen)) == SOCKET_ERROR)
{
TRACE("ERROR : recvfrom - %d .\n", WSAGetLastError());
}
else if(ret != 0)
{
TRACE("ERROR : recvfrom - %d .\n", WSAGetLastError());
{
MsgNum2++;
EnterCriticalSection(&m_cs);
m_arrayDevice.Add(*buff);
LeaveCriticalSection(&m_cs);
}
TRACE("ret : %d .\n", ret);
}
SetEvent(m_hEvent);
break;
主要代码如上
#11
消息触发不会丢, 我想是你写错. 另开线程循环recvfrom效率较高, 而且要写的代码都是一样的. 毕竟UDP其实不用READ, WRITE, CLOSE, ACCEPT这些, 单纯只要READ和CLOSE的错误检测就可以了, 写个线程更容易明白而已..
#12
FD_CONNECT.. tcp才有建立连接吧.
FD_WRITE 可写消息一般无用的。不用检测.
FD_WRITE 可写消息一般无用的。不用检测.
#13
我开线程循环recvfrom试了一下,还是会出现一样的问题。
通过其他实验也确实证明,是这个程序在多个包同时(或间隔很小)到时会丢掉一些。师傅告诉说要控制接收时的时序,在一个包接收处理时,另来一个包,是会被丢掉。
关键是怎么处理?
#14
你用UDP玩分包传送, 这个就问题很大了, 丢包是肯定会有的.
想用UDP实现安全传送方式, 可以参考TCP的滑动窗体, 三次握手等等的方式, 再自己建立机制的.
一般流程上来说就是:
假设采用512B作为一包来发送. 客户端现有4K要发送. 那么将会划分成9个包分别发送(不是算错数)
1. 客户端把4K数据分包, 划分成有包头+序号+数据内容的每份UDP包.
2. 服务器收到UDP包之后, 解释, 回复给客户端, 告诉客户端这个序号的数据已经接收到了, 假如重复了, 就直接回复收到, 不作其他处理.
3. 客户端接收到服务器回复后, 就发下一个序号, 否则就继续发送当前序号.
如此方式让服务器把所有数据包接收完成, 排序, 组合, 再进行相应业务处理.
不过上述的流程只是为了简单化描述, 效率很低的. 但原理比较容易明白.
想用UDP实现安全传送方式, 可以参考TCP的滑动窗体, 三次握手等等的方式, 再自己建立机制的.
一般流程上来说就是:
假设采用512B作为一包来发送. 客户端现有4K要发送. 那么将会划分成9个包分别发送(不是算错数)
1. 客户端把4K数据分包, 划分成有包头+序号+数据内容的每份UDP包.
2. 服务器收到UDP包之后, 解释, 回复给客户端, 告诉客户端这个序号的数据已经接收到了, 假如重复了, 就直接回复收到, 不作其他处理.
3. 客户端接收到服务器回复后, 就发下一个序号, 否则就继续发送当前序号.
如此方式让服务器把所有数据包接收完成, 排序, 组合, 再进行相应业务处理.
不过上述的流程只是为了简单化描述, 效率很低的. 但原理比较容易明白.
#15
我没分包啊,一共才176byte的数据。只是重复发了几十次以模拟多台机器。
要控制接收时的时序,在一个包接收处理时,另来一个包,是会被丢掉。
一个包可以理解为一帧,就是一台机器a发出的数据。
在处理这个数据的时候,另一台b也发来数据了。
之后的具体过程是什么样的?
我的理解是,a的数据进入缓存区,触发一个消息FD_READ,进入OnReceive处理,这时b的数据到了,也进入缓存区,同时触发一个消息(在消息泵 里未取出),等待a的消息处理完后,响应b的消息FD_READ。
但师傅所说的我理解为:b会中断a的处理,没有得到相应就被丢掉了,
实际情况是确实会丢掉(如果a,b发送直接添加时间一定的间隔就不会)。
还是请大侠分析以上场景的处理过程 + 如果确实存在这种丢包的情况,如何处理?
要控制接收时的时序,在一个包接收处理时,另来一个包,是会被丢掉。
一个包可以理解为一帧,就是一台机器a发出的数据。
在处理这个数据的时候,另一台b也发来数据了。
之后的具体过程是什么样的?
我的理解是,a的数据进入缓存区,触发一个消息FD_READ,进入OnReceive处理,这时b的数据到了,也进入缓存区,同时触发一个消息(在消息泵 里未取出),等待a的消息处理完后,响应b的消息FD_READ。
但师傅所说的我理解为:b会中断a的处理,没有得到相应就被丢掉了,
实际情况是确实会丢掉(如果a,b发送直接添加时间一定的间隔就不会)。
还是请大侠分析以上场景的处理过程 + 如果确实存在这种丢包的情况,如何处理?
#16
你看你接收一个包处理时间多少时间,如果时间长,你就要放到队列中做缓冲用。
#17
我怀着试一试的心情把FD_WRITE| FD_CONNECT注释掉,竟然就不会再出现问题了。
有高手能解释么?
int ret = WSAAsyncSelect(m_sockRecv, m_hWnd, WM_MULTIPOINTEVENT,
FD_READ/* | FD_WRITE | FD_CONNECT*/);
#18
问题找到了,所有这些奇异现象,由“360杀毒软件”引起,只要关闭即可!
耽误了一个星期。。。。真悲剧。。
耽误了一个星期。。。。真悲剧。。
#19
360果然是流氓
#20
鄙视360杀毒,妈的捣蛋鬼
#21
#1
什么意思啊,没人回复,也看不到浏览数。。。。。
各位大侠千万不要不屑于回答我啊,随便说两句,指点迷津啊
各位大侠千万不要不屑于回答我啊,随便说两句,指点迷津啊
#2
估计是事件触发问题。
WSAAsyncSelect是边缘触发,要 recvfrom 的错误码为 EWOULDBLOCK 才会产生下个FD_READ。
可能lz收到消息后只recvfrom一次。
不是,常规使用方式下,消息还是传递到界面线程,不会另建线程,也不会并行处理。
WSAAsyncSelect是边缘触发,要 recvfrom 的错误码为 EWOULDBLOCK 才会产生下个FD_READ。
可能lz收到消息后只recvfrom一次。
不是,常规使用方式下,消息还是传递到界面线程,不会另建线程,也不会并行处理。
#3
以下摘自百度百科,按他说 每次只要一次就可以了啊:
对FD_READ,FD_OOB和FD_ACCEPT事件,消息传递是"水平触发"(level-triggered)的.这意味着,若调用了重新通知函数并且相关的事件对该调用仍有效,WSAAsyncSelect()消息就将传给应用程序.这为应用程序提供了事件驱动以及不必考虑在任一时刻到达的数据量的能力.考虑下列序列: (i) Windows Sockets DLL在套接口s上接收100字节的数据并传递一个FD_READ消息. (ii) 应用程序启动recv(s,buffptr,50,0)接收50字节. (iii) 由于仍有数据未读,Windows Sockets DLL发送另一个FD_READ消息. 根据以上语义,应用程序不必在收到FD_READ消息时读进所有可读的数据-对应于每一FD_READ消息进行一次recv()调用是恰当的.如果应用程序为一个FD_READ消息而启动了多个recv()调用,它将接收到多个FD_READ消息.这样的应用程序可能希望在开始recv()调用( 通过不为FD_READ事件置位的WSAAsyncSelect()函数调用)之前关闭FD_READ消息.
#4
recvfrom 是单个工作线程么?
如果是,应该没有问题。
如果是,应该没有问题。
#5
采用UDP就不要用什么其他模型了, 直接bind以后就循环recvfrom就行了...毕竟UDP又不用管理SOCKET
#6
边缘触发.. 搞linux的专业术语啊..
一直对udp无爱。。 100多台. tcp也能做啊. 还能保证完整性. udp内网传输理论是超越tcp的
一直对udp无爱。。 100多台. tcp也能做啊. 还能保证完整性. udp内网传输理论是超越tcp的
#7
另开线程循环recvfrom?这跟消息触发有什么区别?为什么消息触发就丢掉一些?
#8
最好别用CSocket类
#9
我没有用CSocket类
#10
int ret = WSAAsyncSelect(m_sockRecv, m_hWnd, WM_MULTIPOINTEVENT,
FD_WRITE | FD_READ | FD_CONNECT);
if(ret == SOCKET_ERROR)
{
TRACE("ERRROR : WSAAsyncSelect - %d .\n", WSAGetLastError());
}
…………………………
case FD_READ:
MsgNum++;
WaitForSingleObject(m_hEvent, INFINITE);
TRACE("MsgNum : %d ", MsgNum);
if((ret = recvfrom(sockfd, buff, BUFFER_SIZE, 0, (sockaddr *) & from, & salen)) == SOCKET_ERROR)
{
TRACE("ERROR : recvfrom - %d .\n", WSAGetLastError());
}
else if(ret != 0)
{
TRACE("ERROR : recvfrom - %d .\n", WSAGetLastError());
{
MsgNum2++;
EnterCriticalSection(&m_cs);
m_arrayDevice.Add(*buff);
LeaveCriticalSection(&m_cs);
}
TRACE("ret : %d .\n", ret);
}
SetEvent(m_hEvent);
break;
主要代码如上
#11
消息触发不会丢, 我想是你写错. 另开线程循环recvfrom效率较高, 而且要写的代码都是一样的. 毕竟UDP其实不用READ, WRITE, CLOSE, ACCEPT这些, 单纯只要READ和CLOSE的错误检测就可以了, 写个线程更容易明白而已..
#12
FD_CONNECT.. tcp才有建立连接吧.
FD_WRITE 可写消息一般无用的。不用检测.
FD_WRITE 可写消息一般无用的。不用检测.
#13
我开线程循环recvfrom试了一下,还是会出现一样的问题。
通过其他实验也确实证明,是这个程序在多个包同时(或间隔很小)到时会丢掉一些。师傅告诉说要控制接收时的时序,在一个包接收处理时,另来一个包,是会被丢掉。
关键是怎么处理?
#14
你用UDP玩分包传送, 这个就问题很大了, 丢包是肯定会有的.
想用UDP实现安全传送方式, 可以参考TCP的滑动窗体, 三次握手等等的方式, 再自己建立机制的.
一般流程上来说就是:
假设采用512B作为一包来发送. 客户端现有4K要发送. 那么将会划分成9个包分别发送(不是算错数)
1. 客户端把4K数据分包, 划分成有包头+序号+数据内容的每份UDP包.
2. 服务器收到UDP包之后, 解释, 回复给客户端, 告诉客户端这个序号的数据已经接收到了, 假如重复了, 就直接回复收到, 不作其他处理.
3. 客户端接收到服务器回复后, 就发下一个序号, 否则就继续发送当前序号.
如此方式让服务器把所有数据包接收完成, 排序, 组合, 再进行相应业务处理.
不过上述的流程只是为了简单化描述, 效率很低的. 但原理比较容易明白.
想用UDP实现安全传送方式, 可以参考TCP的滑动窗体, 三次握手等等的方式, 再自己建立机制的.
一般流程上来说就是:
假设采用512B作为一包来发送. 客户端现有4K要发送. 那么将会划分成9个包分别发送(不是算错数)
1. 客户端把4K数据分包, 划分成有包头+序号+数据内容的每份UDP包.
2. 服务器收到UDP包之后, 解释, 回复给客户端, 告诉客户端这个序号的数据已经接收到了, 假如重复了, 就直接回复收到, 不作其他处理.
3. 客户端接收到服务器回复后, 就发下一个序号, 否则就继续发送当前序号.
如此方式让服务器把所有数据包接收完成, 排序, 组合, 再进行相应业务处理.
不过上述的流程只是为了简单化描述, 效率很低的. 但原理比较容易明白.
#15
我没分包啊,一共才176byte的数据。只是重复发了几十次以模拟多台机器。
要控制接收时的时序,在一个包接收处理时,另来一个包,是会被丢掉。
一个包可以理解为一帧,就是一台机器a发出的数据。
在处理这个数据的时候,另一台b也发来数据了。
之后的具体过程是什么样的?
我的理解是,a的数据进入缓存区,触发一个消息FD_READ,进入OnReceive处理,这时b的数据到了,也进入缓存区,同时触发一个消息(在消息泵 里未取出),等待a的消息处理完后,响应b的消息FD_READ。
但师傅所说的我理解为:b会中断a的处理,没有得到相应就被丢掉了,
实际情况是确实会丢掉(如果a,b发送直接添加时间一定的间隔就不会)。
还是请大侠分析以上场景的处理过程 + 如果确实存在这种丢包的情况,如何处理?
要控制接收时的时序,在一个包接收处理时,另来一个包,是会被丢掉。
一个包可以理解为一帧,就是一台机器a发出的数据。
在处理这个数据的时候,另一台b也发来数据了。
之后的具体过程是什么样的?
我的理解是,a的数据进入缓存区,触发一个消息FD_READ,进入OnReceive处理,这时b的数据到了,也进入缓存区,同时触发一个消息(在消息泵 里未取出),等待a的消息处理完后,响应b的消息FD_READ。
但师傅所说的我理解为:b会中断a的处理,没有得到相应就被丢掉了,
实际情况是确实会丢掉(如果a,b发送直接添加时间一定的间隔就不会)。
还是请大侠分析以上场景的处理过程 + 如果确实存在这种丢包的情况,如何处理?
#16
你看你接收一个包处理时间多少时间,如果时间长,你就要放到队列中做缓冲用。
#17
我怀着试一试的心情把FD_WRITE| FD_CONNECT注释掉,竟然就不会再出现问题了。
有高手能解释么?
int ret = WSAAsyncSelect(m_sockRecv, m_hWnd, WM_MULTIPOINTEVENT,
FD_READ/* | FD_WRITE | FD_CONNECT*/);
#18
问题找到了,所有这些奇异现象,由“360杀毒软件”引起,只要关闭即可!
耽误了一个星期。。。。真悲剧。。
耽误了一个星期。。。。真悲剧。。
#19
360果然是流氓
#20
鄙视360杀毒,妈的捣蛋鬼