UDP TX / RX中的套接字错误

时间:2013-09-07 11:27:48

标签: c++ windows sockets udp

目前我正在编写一个程序,该程序将通过UDP从另一台PC接收消息并将另一条消息发送回此电脑。接收消息正在工作,但是当我想要发回消息时,我在创建套接字时出现(套接字)错误。那么,为什么我会收到错误,并且我的代码在其他部分也是错误的?

SOCKET recv, trans;
WORD wVersionRequested;
WSADATA wsaData;
int err;

wVersionRequested = MAKEWORD( 2, 2 );

err = WSAStartup( wVersionRequested, &wsaData );
if ( err != 0 ) {
  /* Tell the user that we could not find a usable */
   /* WinSock DLL.                                  */
   return 1;
}

char   myname[256], yourname[256];
struct sockaddr_in sa_recv, sa_trans;
struct hostent *hp_recv, *hp_trans;

memset(&sa_recv, 0, sizeof(struct sockaddr_in)); /* clear our address */
memset(&sa_trans, 0, sizeof(struct sockaddr_in));
gethostname(myname, sizeof(myname));        /* who are we? */
hp_recv = gethostbyname("localhost");                 /* get our address info */
//std::cout << hp_recv->h_addrtype << ' ' << hp_recv->h_addr_list << ' ' << hp_recv->h_aliases << ' ' << hp_recv->h_length << ' ' << hp_recv->h_name << ' \n';
if (hp_recv == NULL)                             /* we don't exist !? */
    return(INVALID_SOCKET);
sa_recv.sin_family = hp_recv->h_addrtype;             /* this is our host address */
sa_recv.sin_port = htons(PORTNUM);               /* this is our port number */
recv = socket(AF_INET, SOCK_DGRAM, 0);        /* create the socket */
if (recv == INVALID_SOCKET)
    return INVALID_SOCKET;

/* bind the socket to the internet address */
if (bind(recv, (struct sockaddr *)&sa_recv, sizeof(struct sockaddr_in)) ==
  SOCKET_ERROR) 
{
    closesocket(recv);
    return(INVALID_SOCKET);
}

struct sockaddr from;
int fromlen = sizeof(from);
char inStr[100];
int ret = recvfrom(recv, inStr, sizeof(inStr), 0, &from, &fromlen); 
in_addr * addr = (in_addr * )get_in_addr(&from);
std::cout << "Received " << inStr << " from " << inet_ntoa(*addr);
std::cout << '\n';
closesocket(recv);
std::cout << "Sending Data to " << inet_ntoa(*addr) << '\n'; 
char *ip = NULL;
ip = (char *) get_in_addr(&from);
/*if (from.sa_family == AF_INET)
{
    struct sockaddr_in *sin = (struct sockaddr_in *) from;
    ip = inet_ntoa(sin->sin_addr);
};*/
gethostname(yourname, sizeof(yourname));
/*hp_trans = gethostbyname(ip);
if(hp_trans == NULL)
{
    std::cerr << "hp_trans is zero " << hp_trans << " from " << hp_recv << " and " << &from << '\n';
    getchar();
    return(INVALID_SOCKET);
};*/
memset(&sa_trans,0,sizeof(sa_trans));
memcpy((char *)&sa_trans.sin_addr, ip, hp_recv->h_length);   /* set address */
sa_trans.sin_family = AF_INET;
sa_trans.sin_port = htons(50001);
trans = socket(AF_INET, SOCK_DGRAM, 0);
if(trans == INVALID_SOCKET)
{
    std::cerr << "Trans is an invalid socket " << '\n';
    getchar();
    return INVALID_SOCKET;
};
if(bind(trans, (struct sockaddr *)&sa_trans, sizeof(struct sockaddr_in)) == SOCKET_ERROR)
{
    closesocket(trans);
    std::cout << "bind has failed with error " << WSAGetLastError() << '\n';
    getchar();
    return(INVALID_SOCKET);
};
char str[100] = "Message transmitted. Transmission finished.";
int transmit = sendto(trans, str, sizeof(str), 0, (struct sockaddr *)&sa_trans, sizeof(sa_trans));
std::cout << "Transmission finished. Program will exit. " << '\n';
std::getchar();
return 1;

非常感谢你!

3 个答案:

答案 0 :(得分:1)

我认为问题在于您实际初始化struct sockaddr_insin_addr字段的方式。问题是您无法使用char*初始化此字段,但使用二进制数据。

试试这个:

trans_addr.sin_addr.s_addr = inet_addr(DEST_IP);
  

inet_addr()函数转换来自的Internet主机地址cp   以网络字节顺序将IPv4数字和点符号表示为二进制数据。

甚至更好:

inet_aton("192.168.0.1", &trans_addr.sin_addr); // store IP in trans_addr

或     inet_pton in the world of windows

bind之前放置一个制动点会有所帮助,并检查sa_trans.sin_addr的值是多少。

Windows上的示例: http://msdn.microsoft.com/en-us/library/windows/desktop/ms740148(v=vs.85).aspx

linux上的示例:

    char *secret_message = "The Cheese is in The Toaster";

    int stream_socket, dgram_socket;
    struct sockaddr_in dest_addr;
    int temp;

    dest_addr.sin_family = AF_INET;
    /* short, network byte order */
    dest_addr.sin_port = htons(DEST_PORT);
    dest_addr.sin_addr.s_addr = inet_addr(DEST_IP);

    /* zero the rest of the struct */
    memset(&(dest_addr.sin_zero), 0, 8);

    dgram_socket = socket(dest_addr.sin_family, SOCK_DGRAM, 0);


    // send secret message
    sendto(dgram_socket, secret_message, strlen(secret_message) + 1, 0,
            (struct sockaddr*) &dest_addr, sizeof dest_addr);

答案 1 :(得分:0)

您错误地使用sin_addr。它必须具有4字节大小,每个字节必须包含IP地址数量的值。例如,对于IP地址192.168.1.1,可以按照以下方式对其进行初始化:

unsigned char addr[4] = { 192, 168, 1, 1 }
memcpy(&sa_trans.sin_addr, addr, sizeof(sa_trans.sin_addr));

答案 2 :(得分:0)

发送回复时,您正在创建一个新套接字,将其初始化错误,并告诉它将回复发送给自己而不是另一方。

您应该使用收到请求的同一套接字,并使用sockaddr_in为您提供的recvfrom()(您错误地声明为sockaddr而不是sockaddr_in )知道将回复发送回去的地方,例如:

struct sockaddr_in from;
int fromlen = sizeof(from);
int ret = recvfrom(recv, ..., (struct sockaddr *)&from, &fromlen); 
...
int transmit = sendto(recv, ..., (struct sockaddr *)&sfrom, fromlen);