UDP Echo服务器未在客户端上接收

时间:2014-06-11 10:05:08

标签: c sockets udp sdl-2

我试图用UDP和SDL_Net 2库编写一个简单的echo服务器。 服务器收到数据包正好并尝试将其发送回它所来自的地址,但客户端没有收到任何内容。

这是我的服务器代码(减去一些已被剥离的无关部分):

void main()
{
    /* variables */

    if(!(sd = SDLNet_UDP_Open(2000)))
    {
        printf("Could not create socket\n");
        SDLNet_Quit();
        exit(1);
    }

    if(!(p = SDLNet_AllocPacket(512)))
    {
        printf("Could not allocate packet\n");
        SDLNet_Quit();
        exit(2);
    }

    quit = 0;
    while(!quit)
    {
        if(SDLNet_UDP_Recv(sd, p))
        {
            printf("%s\n", (char*)p->data);
            printf("\tFrom port: %d\n", p->address.port);

            UDPsocket socket = SDLNet_UDP_Open(0);
            if(!socket)
            {
        printf("Could not create socket to send\n");
            }
            else
            {
                printf("\tSending packet\n");
                UDPpacket* send = SDLNet_AllocPacket(512);
                if(!send)
                {
                    printf("Could not allocate packet to send\n");
                }
                else
                {
                    send->address = p->address;
                    send->channel = -1;
                    send->data = (char*)p->data;
                    send->len = strlen((char*)send->data) + 1;
                    send->status = 0;
                    SDLNet_UDP_Send(socket, -1, send);
                }
            }
        }
    }

    /* cleanup */
}

所以在服务器端,我基本上是在端口2000上监听传入的数据包,然后在接收数据包时发回一个数据包。

这是客户的代码(再次,部分内容被删除):

void main()
{
    SDLNet_Init();

    if(!(sd = SDLNet_UDP_Open(0)))
    {
        printf("Could not create socket\n");
        SDLNet_Quit();
        SDL_Quit();
        exit(1);
    }

    IPaddress* myaddress = SDLNet_UDP_GetPeerAddress(sd, -1);
    if(!myaddress)
    {
        printf("Could not get own port\n");
        exit(2);
    }
    printf("My port: %d\n", myaddress->port);
    UDPpacket* recvp = SDLNet_AllocPacket(512);
    if(!recvp)
    {
        printf("Could not allocate receiving packet\n");
        exit(3);
    }

    UDPsocket socket;
    socket = SDLNet_UDP_Open(myaddress->port);
    if(!socket)
    {
        printf("Could not allocate receiving socket\n");
        exit(4);
    }

    // resolve server host
    SDLNet_ResolveHost(&srvadd, "localhost", 2000);

    if(!(p = SDLNet_AllocPacket(512)))
    {
        printf("Could not allocate packet\n");
        SDLNet_Quit();
        SDL_Quit();
        exit(2);
    }

    p->address.host = srvadd.host;
    p->address.port = srvadd.port;

    /* ... */
    while(run)
    {
        if(SDLNet_UDP_Recv(socket, recvp))
        {
            printf("Receiving packet\n");
            char* data = (char*)recvp->data;
            if(strcmp(data, "left") == 0)
            {
                printf("received left\n");
            }
        }

        SDL_Event e;
        while(SDL_PollEvent(&e))
        {
            if(e.type == SDL_KEYDOWN)
            {
                switch(e.key.keysym.sym)
                {
                    case SDLK_LEFT:
                        p->data = "left";
                        p->len = strlen("left") + 1;
                        SDLNet_UDP_Send(sd, -1, p);
                        break;
                    case SDLK_RIGHT:
                        p->data = "right";
                        p->len = strlen("right") + 1;
                        SDLNet_UDP_Send(sd, -1, p);
                        break;
                    default:
                        break;
                }
            }
        }
    }

    /* cleanup */
}

因此客户端发送到达服务器的数据包,同时也会监听(但从不听任何事情)。请注意,这些都是非阻塞调用。

我需要做些额外的事吗?我做错了吗?

2 个答案:

答案 0 :(得分:1)

我认为问题是你在第一次发送时设置p.address的方式。在文档中声明SDLNet_ResolveHost以网络字节顺序返回IP地址,而不是本机顺序,因此可以从表示127.0.0.1的整数更改为相反的:1.0.0.127。

你可以看到它进行快速调试。希望这可以帮助。此外,文档不是非常精确,因为使用网络订单或本机订单,我不是SDLNet的专家。

答案 1 :(得分:0)

你做了很多错事。 我写了一个简单的服务器:

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <arpa/inet.h>

#include "SDL_net.h"

main(int argc, char *argv[]) {
    IPaddress serverIP;
    UDPsocket udpsock;
    UDPpacket* recv_packet;
    SDLNet_SocketSet socketset = NULL;
    int numused;
    static const int MAX_PACKET_SIZE = 512;

    if (SDLNet_Init() < 0) {
      printf("Couldn't initialize net: %s\n", SDLNet_GetError());
      exit(1);
    }

    udpsock = SDLNet_UDP_Open(3333);
    if(!udpsock) {
      printf("SDLNet_UDP_Open: %s\n", SDLNet_GetError());
      exit(2);
    } else {
      printf("listening on 0.0.0.0:3333\n");
    }

    socketset = SDLNet_AllocSocketSet(2);
    if ( socketset == NULL ) {
      fprintf(stderr, "Couldn't create socket set: %s\n", SDLNet_GetError());
      exit(2);
    }

    numused = SDLNet_UDP_AddSocket(socketset,udpsock);
    if(numused==-1) {
      printf("SDLNet_AddSocket: %s\n", SDLNet_GetError());
      exit(2);
    }

    recv_packet = SDLNet_AllocPacket(MAX_PACKET_SIZE);
    if(!recv_packet) {
      printf("Could not allocate packet\n");
      exit(2);
    }

    while(1) {
      SDLNet_CheckSockets(socketset, ~0);
      if (SDLNet_SocketReady(udpsock)) {
        if (SDLNet_UDP_Recv(udpsock, recv_packet)) {
          SDLNet_UDP_Send(udpsock, -1, recv_packet);

          //format log
          int len = recv_packet->len;
          char temp[MAX_PACKET_SIZE+2];
          memcpy(temp, recv_packet->data, len);

          if (temp[len-1] == '\n') {
           temp[len-1] = '\\';
           temp[len] = 'n';
           temp[len+1] = '\0';
          } else {
           temp[len] = '\0';
          }

          char hoststring[128];
          inet_ntop(AF_INET,&recv_packet->address.host,hoststring,128),

          printf("got: \"%s\" from: %s:%d\n",
              temp,
              hoststring,
              ntohs(recv_packet->address.port));
        }
      }
    }
    return 0;
}

您可以使用:$ nc -u localhost 3333

进行测试