简体   繁体   English

UDP测试代码未接收到消息(C ++)

[英]UDP test code not receiving messages (C++)

Firstly, please pardon the mess. 首先,请原谅。 I've been trying to modify example UDP code to work across windows/linux. 我一直在尝试修改示例UDP代码以在Windows / Linux中工作。 There're probably a few blips of windows-specific code still laying around where I've been trying to figure out what on earth is going wrong. 我一直试图找出到底哪里出了问题,可能仍然有一些Windows特定代码的漏洞。

This is my first time working with UDP instead of TCP. 这是我第一次使用UDP而不是TCP。

If I uncomment the recvfrom stuff in the client, it blocks indefinitely IFF the the server is running. 如果我取消注释客户端中的recvfrom内容,则它将无限期地阻止服务器运行。 Otherwise it returns immediately, as expected. 否则,它会按预期返回。 What I can't seem to figure out, is why my server, in its current state, can't seem to receive anything at all from the client. 我似乎无法弄清楚的是,为什么我的服务器在当前状态下根本无法从客户端接收任何信息。

What am I missing here? 我在这里想念什么?

Btw, I should also mention that if I bind the socket for the serverAddress from within the client and try to let it receive from itself (omitting the server altogether), it has no trouble doing so. 顺便说一句,我还应该提到,如果我从客户端内部绑定serverAddress的套接字,并尝试使其从自身接收(完全省略服务器),这样做就没有麻烦了。 (Also, I haven't tried this version on linux yet.) (此外,我还没有在Linux上尝试过此版本。)

Thanks 谢谢

Server (receiver): 服务器(接收方):

#ifdef _WIN32 || _WIN64 || _WINDOWS_
#include <WinSock2.h>
#pragma comment(lib, "Ws2_32.lib")
#define __COMPILE_FOR_WINDOWS__
#define SOCKET_INVALID(s) (s==INVALID_SOCKET)
#define SOCKET_TYPE SOCKET
#endif
#ifdef linux
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <string.h>
#define SOCKET_INVALID(s) (s<0)
#define SOCKET_TYPE int
#endif

#include <iostream>

#define BUFFER_LENGTH  1024

int main(int argc, char** argv)
{

#ifdef __COMPILE_FOR_WINDOWS__
    WSADATA wsaData;
    if (WSAStartup(MAKEWORD(2, 2), &wsaData) != NO_ERROR)
    {
        std::cerr << "could not start up winsock-2.2\n";
        return 1;
    }
#endif 

    struct sockaddr_in serverAddress,
        clientAddress;
    unsigned short Port = 27015;
    char RecvBuf[BUFFER_LENGTH];

    SOCKET_TYPE socketHandle = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP/* or 0? */);
    if (SOCKET_INVALID(socketHandle))
    {
        std::cerr << "could not make socket\n";
        return 1;
    }

    memset(&serverAddress, 0, sizeof(serverAddress));
    serverAddress.sin_family = AF_INET;
    serverAddress.sin_port = htons(Port);
    serverAddress.sin_addr.s_addr = htonl(INADDR_ANY);

    if (bind(socketHandle, (struct sockaddr*)&serverAddress, sizeof(serverAddress)) != 0)
    {
        std::cerr << "could not bind socket\n";
        return 1;
    }

    int len;
    int client_addr_len;// = sizeof(clientAddress);
    while (1)
    {
        len = recvfrom(socketHandle,RecvBuf,BUFFER_LENGTH,0,(struct sockaddr*)&clientAddress,&client_addr_len);
        if (strncmp(RecvBuf,"END",3)==0) 
            break;
        if (len > 0)
        {
            //sendto(socketHandle, RecvBuf, len, 0, (struct sockaddr*)&clientAddress, sizeof(clientAddress));
            RecvBuf[len] = 0;
            std::cout << "received: " << RecvBuf << std::endl;
        }
    }

#ifdef __COMPILE_FOR_WINDOWS__
    closesocket(socketHandle);
    WSACleanup();
#endif
#ifdef linux
    close(socketHandle);
#endif
    std::cout<< "done\n";
    return 0;
}

#ifdef __COMPILE_FOR_WINDOWS__
#undef __COMPILE_FOR_WINDOWS__
#endif

#undef BUFFER_LENGTH
#undef SOCKET_INVALID

#ifdef SOCKET_TYPE
#undef SOCKET_TYPE
#endif

Client (sender): 客户(发送者):

#ifdef _WIN32 || _WIN64 || _WINDOWS_
#include <WinSock2.h>
#pragma comment(lib, "Ws2_32.lib")
#define __COMPILE_FOR_WINDOWS__
#define SOCKET_INVALID(s) (s==INVALID_SOCKET)
#define SOCKET_TYPE SOCKET
#endif
#ifdef linux
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <string.h>
#define SOCKET_INVALID(s) (s<0)
#define SOCKET_TYPE int
#endif

#include <iostream>

#define BUFFER_LENGTH  1024

int main(int argc, char** argv)
{

#ifdef __COMPILE_FOR_WINDOWS__
    WSADATA wsaData;
    if (WSAStartup(MAKEWORD(2, 2), &wsaData) != NO_ERROR)
    {
        std::cerr << "could not start up winsock-2.2\n";
        return 1;
    }
#endif 

    struct sockaddr_in serverAddress,
        clientAddress;
    unsigned short Port = 27015;
    char msgBuf[BUFFER_LENGTH];

    SOCKET_TYPE socketHandle = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP/* or 0? */);
    if (SOCKET_INVALID(socketHandle))
    {
        std::cerr << "could not make socket\n";
        return 1;
    }

    //char address[512];
    //std::cout << "enter ip: ";
    //std::cin.getline(address, 512);

    memset(&serverAddress, 0, sizeof(serverAddress));
    serverAddress.sin_family = AF_INET;
    serverAddress.sin_port = htons(Port);
    serverAddress.sin_addr.s_addr = inet_addr("127.0.0.1");

    int len;
    std::cout << "gimme something: ";
    std::cin.getline(msgBuf, BUFFER_LENGTH);

    while (1)
    {
        int n = sendto(socketHandle,msgBuf, strlen(msgBuf), 0,(struct sockaddr*)&serverAddress, sizeof(serverAddress));
        std::cout << "sent "<<n<<" bytes of the msg\n";
        /*len = recvfrom(socketHandle,msgBuf,BUFFER_LENGTH, 0, NULL, NULL);
        if (len > 0)
        {
            msgBuf[len] = 0;
            fputs(msgBuf, stdout);
        }else if(len < 0)std::cerr << "windowsy error\n";*/
    }

#ifdef __COMPILE_FOR_WINDOWS__
    closesocket(socketHandle);
    WSACleanup();
#endif
#ifdef linux
    close(socketHandle);
#endif
    std::cout << "done\n";
    return 0;
}

#ifdef __COMPILE_FOR_WINDOWS__
#undef __COMPILE_FOR_WINDOWS__
#endif

#undef BUFFER_LENGTH
#undef SOCKET_INVALID

#ifdef SOCKET_TYPE
#undef SOCKET_TYPE
#endif

I didn't see any error, so i compiled both programs on my machine (openSuSE 11.3). 我没有看到任何错误,所以我在我的机器上(openSuSE 11.3)都编译了这两个程序。 Only thing i had to change was int client_addr_len to socklen_t client_addr_len Communication worked immediately. 我唯一需要更改的是将int client_addr_len更改为socklen_t client_addr_len通信立即生效。 (Of course the client ran into the endless while(1) loop). (当然,客户端遇到了无尽的while(1)循环)。

Are you doing this on one machine, or on 2? 您是在一台或两台计算机上执行此操作? The client always sends to localhost, so 2 different machines won't work. 客户端始终发送到localhost,因此2台不同的计算机将无法工作。 Is there any firewall blocking communication? 是否有防火墙阻止通信?

Try to do a 'netstat -au | 尝试做一个'netstat -au | grep 27015' before and after starting the server. grep 27015'在启动服务器之前和之后。 Is anything else listening on that socket before you start the server? 在启动服务器之前,还有其他监听该套接字的事情吗? Is the server listening after you start it? 服务器启动后是否在监听?

Try to start the client and server with strace. 尝试使用strace启动客户端和服务器。 Do you see any system call errors? 您是否看到任何系统调用错误?

Found the problem! 发现了问题! I had to uncomment the part for client_addr_len=sizeof(clientAddress);. 我必须取消注释client_addr_len = sizeof(clientAddress);的部分。

For some reason, I thought that variable looked more like it was designed to receive a length for addresses of varying size from the recvfrom() function, so I doubted rather it really needed an initial value. 由于某种原因,我认为变量看起来更像是设计为从recvfrom()函数接收长度可变的地址的长度,因此我怀疑它是否确实需要初始值。 This was the only way to make the datagrams start flying. 这是使数据报开始飞行的唯一方法。 :P :P

Also, to any future readers, the socklen_t issue can be quickly patched by adding 此外,对于以后的读者来说,可以通过添加socklen_t问题来快速解决问题

typedef int socklen_t;

to the windows specific section of the top directives, and changing the int len; 到top指令的Windows特定部分,并更改int len; to socklen_t len; ckle - like Guntram said. 就像贡特拉姆说的那样

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM