UDP 无法接收包,似乎阻塞了...小弟新手,跪求各位大哥,在线等!谢谢大家...

showmeout 2012-03-09 03:22:26
int recv;
SOCKADDR_IN addrSend;
int len = sizeof(SOCKADDR_IN);
SOCKET RecvSocket;
struct sockaddr_in RecvAddr;

InitWinsock();
RecvSocket = socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP);

RecvAddr.sin_family = AF_INET;
RecvAddr.sin_port = htons(7778);
RecvAddr.sin_addr.S_un.S_addr =htonl(INADDR_ANY);

//在此设置非阻塞
//unsigned long iMode = 1;//为0时阻塞,非0时不阻塞
//::ioctlsocket(RecvSocket,FIONBIO,&iMode);

bind(RecvSocket,(LPSOCKADDR)&RecvAddr,sizeof(SOCKADDR_IN));

char recvBuf[1024];
SOCKADDR_IN addrClient;
while(1)
{
pthread_mutex_lock(&mut);
recv = recvfrom(RecvSocket,recvBuf,1024,0,(LPSOCKADDR)&addrSend,&len);
printf("Recvfrom failed:%d\n", WSAGetLastError());
pthread_mutex_unlock(&mut);
Sleep(1000);

}
closesocket(RecvSocket);

这是一段在main中新开的一个线程的函数中的代码,我能发送数据,但这段接受数据报的代码在recvfrom处好像阻塞,在服务器端调试发现数据确实有发送出来。。。 求救啊, ps. 另外我发送数据一切正常

...全文
561 33 打赏 收藏 转发到动态 举报
写回复
用AI写文章
33 条回复
切换为时间正序
请发表友善的回复…
发表回复
showmeout 2012-03-17
  • 打赏
  • 举报
回复
[Quote=引用 32 楼 kevin_qing 的回复:]

把基本结构,和一些简单的inline工具函数提到 比如叫 maininclude.h,这里面的东西只供其他文件使用,没有交叉引用。
然后把需要的pre define 的struct function 在提到另外一个比如predefine.h里面

其他cpp/c include 这2个就行了
[/Quote]

不需要像C++那样,把每个模块都拆分成.c和.h文件来写吗?大侠,还想请问一下,在c里面有没有什么比较简单的开源代码用来绘制简单的直线曲线图形的呢?
showmeout 2012-03-16
  • 打赏
  • 举报
回复
[Quote=引用 30 楼 kevin_qing 的回复:]
这样?
windows机器是否开了防火墙?


1个socket很好处理啊

简单的做法

server:
while(run){
用select判断有无read,需设置超时。比如1秒(也可以用nonblock直接读)

有read数据,调用recvfrom 然后更新clientAddr.

检查是否有数据需发送给客户端clientaddr。是则发送。
}


……
[/Quote]


哥们解决了,非常感谢... 该死的防火墙,呵呵... 顺便问一下,我在VS下写C语言的程序,怎么在其他文件中组织全局函数、全局变量、宏、头文件之类的呢,老是容易出现重定义或者无定义之类的错误...
Kevin_qing 2012-03-16
  • 打赏
  • 举报
回复
把基本结构,和一些简单的inline工具函数提到 比如叫 maininclude.h,这里面的东西只供其他文件使用,没有交叉引用。
然后把需要的pre define 的struct function 在提到另外一个比如predefine.h里面

其他cpp/c include 这2个就行了
Kevin_qing 2012-03-12
  • 打赏
  • 举报
回复
你用另外一个socket发送的,那么接收端收到的addr->port就是另外一个socket 的。
返回的数据也是到另外一个socket。

你应该只用一个socket收发,如果非要用2个,你要设法通知对方接收端口。

因为可能有nat的原因,不建议用2个端口
showmeout 2012-03-12
  • 打赏
  • 举报
回复
[Quote=引用 24 楼 kevin_qing 的回复:]

代码上没什么问题。有可能是逻辑处理上面有什么错误。

根据你的描述,linux返回数据的地址是接收到请求时确定的。但我没看到你发送数据。
难道你用另外一个socket发送的?

btw:recvBuf太小,数据可能会被截断,弄大点吧。
[/Quote]

是的,我用另外一个socket发送的,是这里的原因吗???
Kevin_qing 2012-03-12
  • 打赏
  • 举报
回复
这样?
windows机器是否开了防火墙?


1个socket很好处理啊

简单的做法

server:
while(run){
用select判断有无read,需设置超时。比如1秒(也可以用nonblock直接读)

有read数据,调用recvfrom 然后更新clientAddr.

检查是否有数据需发送给客户端clientaddr。是则发送。
}


client:

发送请求
while(run){
接收数据。
}



更可靠的方法需要制造一个通讯协议,比如client发送请求后,需要定时告诉server他还活着。

这样当客户端退出后,server可以通过超时知道现在没有客户端,从而停止发送。


showmeout 2012-03-12
  • 打赏
  • 举报
回复
[Quote=引用 28 楼 kevin_qing 的回复:]

我大概明白你是怎么做的了。

你本机是局域网,linux在外网。

因为nat的关系,本机7788 映射的端口不一定是7788,所以外网回应的包是收不到的。

通常的做法。

server: 监听7788 ,处理请求,返回值来源地址(recvfrom里面获得的地址)

client:不用bind,直接发送至server:7788,发送请求后 recvfrom。这里要做处理丢包……
[/Quote]

哥们儿,我的主机除了一个有线网卡(用来上互联网)还有一个usb无线网卡,linux端相当于一个wifi热点,我通过usb网卡连上linux端,在这个网络里只有我们两个机子;我把有线网卡拔掉禁用之后依然不行啊...

由于linux端要不断往上传数据,因此我才打算开两个socket,其中这个出问题的socket就是我在新进程中接受数据的;而上位机只是随机向下位机发送数据的,所以我在main函数中处理了,所以我才考虑用两个socket了... 哥们儿,要是用一个socket好像不好实现啊... 小弟还是没有明白您的意思!
Kevin_qing 2012-03-12
  • 打赏
  • 举报
回复
我大概明白你是怎么做的了。

你本机是局域网,linux在外网。

因为nat的关系,本机7788 映射的端口不一定是7788,所以外网回应的包是收不到的。

通常的做法。

server: 监听7788 ,处理请求,返回值来源地址(recvfrom里面获得的地址)

client:不用bind,直接发送至server:7788,发送请求后 recvfrom。这里要做处理丢包超时,超时后重新发送请求。

2边都只有1个socket

showmeout 2012-03-12
  • 打赏
  • 举报
回复
[Quote=引用 26 楼 kevin_qing 的回复:]

你用另外一个socket发送的,那么接收端收到的addr->port就是另外一个socket 的。
返回的数据也是到另外一个socket。

你应该只用一个socket收发,如果非要用2个,你要设法通知对方接收端口。

因为可能有nat的原因,不建议用2个端口
[/Quote]

哥们儿说的通知对方接受端口具体是指linux端还是我本机这边呢?因为linux端发送的端口号我用的7778,我在本机上直接用7778不可以吗?
如果用一个socket,下位机linux端收发用不同的端口会引起什么问题啊?
showmeout 2012-03-11
  • 打赏
  • 举报
回复
void *udpLoggerFunction(void * args)
{
int recv;
SOCKADDR_IN addrSend;
int len = sizeof(SOCKADDR_IN);
SOCKET RecvSocket; //for receiving
struct sockaddr_in RecvAddr;
//win-socket configuration, for socket
InitWinsock();
RecvSocket = socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP); //for receiving

RecvAddr.sin_family = AF_INET;
RecvAddr.sin_port = htons(7778);
RecvAddr.sin_addr.S_un.S_addr =htonl(INADDR_ANY);

//设置为非阻塞
//unsigned long iMode = 1;//为0时阻塞,非0时不阻塞
//::ioctlsocket(RecvSocket,FIONBIO,&iMode);

int err = bind(RecvSocket,(LPSOCKADDR)&RecvAddr,sizeof(SOCKADDR_IN));
if (err == SOCKET_ERROR)
{
printf("Bind failed:%d\n", WSAGetLastError());
closesocket(RecvSocket);
WSACleanup();
return NULL;
}
char recvBuf[128];
while(1)
{
pthread_mutex_lock(&mut);
recv = recvfrom(RecvSocket,recvBuf,128,0,(LPSOCKADDR)&addrSend,&len);
if (recv <= 0)
{
printf("[%d]Recvfrom failed:%d\n", recv, WSAGetLastError());
pthread_mutex_unlock(&mut);
continue;
}
log.msgcount++;
printf("\nRecvied message successfully: %s",getNowTime());
pthread_mutex_unlock(&mut);
Sleep(1000);
}
closesocket(RecvSocket);
return NULL;
}


 
IPEndPoint ipep = new IPEndPoint(IPAddress.Any, Port);
newsock = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
newsock.Bind(ipep);
//Console.WriteLine("Waiting for a client...");
IPEndPoint sender = new IPEndPoint(IPAddress.Any, 0);
Remote = (EndPoint)(sender);

//接受数据报代码
recv = newsock.ReceiveFrom(data, ref Remote);
string s = Encoding.ASCII.GetString(data, 0, recv);


上面第一段代码是我在C/C++下面的代码,无法使用;同样的机子,同样的网络,第二段C#代码却可以使用,小弟实在很无奈无奈啊... 求帮助求帮助求帮助求帮助求帮助求帮助求帮助求帮助求帮助求帮助!!!!
showmeout 2012-03-11
  • 打赏
  • 举报
回复
[Quote=引用 19 楼 fenglllin 的回复:]

还是显式指定IP吧,确保绑定成功.再不行只有看高手的了。
C/C++ code

RecvAddr.sin_addr.s_addr=inet_addr("XXX");
[/Quote]

嗯,我这就试试...
Kevin_qing 2012-03-11
  • 打赏
  • 举报
回复
代码上没什么问题。有可能是逻辑处理上面有什么错误。

根据你的描述,linux返回数据的地址是接收到请求时确定的。但我没看到你发送数据。
难道你用另外一个socket发送的?

btw:recvBuf太小,数据可能会被截断,弄大点吧。





showmeout 2012-03-11
  • 打赏
  • 举报
回复
[Quote=引用 22 楼 oniisama 的回复:]
那可能是你的pthread_mutex_lock无法获得锁的原因吧
[/Quote]
应该不是,我删除了这个也不行,而且调试发现就是卡在了接受哪里:
 recv = recvfrom(RecvSocket,recvBuf,128,0,(LPSOCKADDR)&addrSend,&len);  
, 应该就是阻塞了,但是发送端确实有发送啊... 而且C#的代码应该也是阻塞方式的。。。
oniisama 2012-03-11
  • 打赏
  • 举报
回复
那可能是你的pthread_mutex_lock无法获得锁的原因吧
fenglllin 2012-03-10
  • 打赏
  • 举报
回复
还是显式指定IP吧,确保绑定成功.再不行只有看高手的了。

RecvAddr.sin_addr.s_addr=inet_addr("XXX");
showmeout 2012-03-10
  • 打赏
  • 举报
回复
[Quote=引用 17 楼 yangcao123 的回复:]

非阻塞模式下,调用接受函数会马上返回,你可以通过判断,用循环接收数据

while(1){
if(SOCKET_ERROR ==recvfrom())
{
if(WSAEWOULDBLOCK==GetLastError()){
continue;
}
else{
printf("接受失败");
……
[/Quote]

我也试过非阻塞方式,发现recvfrom函数一直都会返回错误。。。 只有明天再去看看到底咋回事啊... 疯了都!
oniisama 2012-03-10
  • 打赏
  • 举报
回复
光根据sendto的返回值是无法判断是否发送成功的,你可以试试在linux端能否connect你要发送的ip
yangcao123 2012-03-10
  • 打赏
  • 举报
回复
非阻塞模式下,调用接受函数会马上返回,你可以通过判断,用循环接收数据

while(1){
if(SOCKET_ERROR ==recvfrom())
{
if(WSAEWOULDBLOCK==GetLastError()){
continue;
}
else{
printf("接受失败");
break;
}
}
//运行到这里时就是接受了数据
break;
}
showmeout 2012-03-10
  • 打赏
  • 举报
回复
[Quote=引用 12 楼 fenglllin 的回复:]

收端只有一个网卡吧,这个就不知道怎么回事了,要不再看看绑定成功没?
[/Quote]

绑定没有问题吧,因为bind没有返回错误...
showmeout 2012-03-10
  • 打赏
  • 举报
回复
[Quote=引用 13 楼 oniisama 的回复:]

光根据sendto的返回值是无法判断是否发送成功的,你可以试试在linux端能否connect你要发送的ip
[/Quote]

我在linux端能接受到上位机的数据,发送的时候也能确定sendto函数是调用了的... UDP不需要connect就能发送啊,哥们儿,跪求怎么验证你说的这个问题呢?
加载更多回复(13)

64,683

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧