如何在c中接收winsock的udp数据包?

作为一个包围我的头围绕udp套接字的尝试,我试图将代码从本教程页面 http://www.linuxhowtos.org/C_C++/socket.htm移植到winsock(运行在win 8,如果重要). [下面的直接链接]

代码当前编译并运行,但是我从来没有收到数据包,这两个程序只是等待并阻止recvfrom().我不断有这个同样的问题(例如,使用这个代码https://stackoverflow.com/a/679529/873217修改版本,包括一个recvfrom()调用,并用这个代码C++ problem with Datagram (UDP)winsocket to sendto and recvfrom on the same socket through the loopback adapter进行更改).我想我正在做一些简单和根本的错误;但我无法自己找到它.希望有更多经验的人可以为我解决这个问题.谢谢.

补充笔记:
我正在运行服务器exe然后客户端exe在同一台计算机上.它被连接到互联网.我也尝试使用一个解析到我的IP地址的域名.我也尝试禁用防火墙,尽管我允许这两个程序完全访问.

直接链接到原始客户端和服务器代码
http://www.linuxhowtos.org/data/6/client_udp.c
http://www.linuxhowtos.org/data/6/server_udp.c

我目前的尝试:

两者都链接到libws2_32.a

客户端代码

#include <stdio.h>
#include <winsock2.h>
#include <string.h>

void error(const char *);

int main()
{
    WSAData data;
    WSAStartup( MAKEWORD( 2,2 ),&data );

    int sock,n;
    int length;
    struct sockaddr_in server,from;
    struct hostent *hp;
    char buffer[256];
    unsigned short serverPort = 27072;
    sock = socket(AF_INET,SOCK_DGRAM,0);
    if (sock < 0) error("socket");
    server.sin_family = AF_INET;
    hp = gethostbyname("localhost");//have also tried my url
    if (hp==0) error("UnkNown host");
    memmove((char *)hp->h_addr,(char *)&server.sin_addr,hp->h_length);
    server.sin_port = htons(serverPort);
    length = sizeof(struct sockaddr_in);
    printf("Please enter the message: ");
    memset(buffer,256);
    fgets(buffer,255,stdin);
    n = sendto (sock,buffer,strlen(buffer),(const struct sockaddr *)&server,length);
    if (n < 0) error("Sendto");
    printf("sent %i bytes\n",n);
    n = recvfrom(sock,256,(struct sockaddr *)&server,&length);
    if (n < 0) error("recvfrom");
    //write(1,"Got an ack: ",12);
    //write(1,n);
    printf("Got msg: %s\n",buffer);

    closesocket(sock);
    WSACleanup();
    return(0);
}

void error(const char *msg)
{
    perror(msg);
    exit(0);
}

服务器代码

#include <stdio.h>
#include <winsock2.h>
#include <string.h>

void error(const char *);

int main()
{
    WSAData data;
    WSAStartup( MAKEWORD( 2,length,n;
    int fromlen;
    struct sockaddr_in server;
    struct sockaddr_in from;
    char buf[1024];
    unsigned short serverPort = 27072;
    sock=socket(AF_INET,0);
    if (sock < 0) error("opening socket");
    length = sizeof(server);
    memset(&server,length);
    server.sin_family = AF_INET;
    server.sin_addr.s_addr=INADDR_ANY;
    server.sin_port=htons(serverPort);
    if (bind(sock,length)<0) error ("binding");
    fromlen = sizeof(struct sockaddr_in);
    while(1)
    {
        n = recvfrom(sock,buf,1024,(struct sockaddr *)&from,&fromlen);
        if (n<0) error("recvfrom");
        //write(1,"Received a datagram: ",21);
        //write(1,n);
        printf("Received a datagram: %s",buf);
        n = sendto(sock,"Got your message\n",17,fromlen);
        if (n<0)error("sendto");
    }
    closesocket(sock);
    WSACleanup();
    return 0;
}


void error (const char *msg)
{
    perror(msg);
    exit(0);
}

解决方法

以下UDP测试应用程序在我的设置 – Windows 7,VS 2013上正常工作.

我创建了一些轻量级的包装类来进行资源管理,并将错误代码转换为异常.这使得客户端和服务器代码更容易阅读.请务必先运行服务器.

Network.h

#include <WinSock2.h>
#include <WS2tcpip.h>
#include <system_error>
#include <string>
#include <iostream>

#pragma once

class WSASession
{
public:
    WSASession()
    {
        int ret = WSAStartup(MAKEWORD(2,2),&data);
        if (ret != 0)
            throw std::system_error(WSAGetLastError(),std::system_category(),"WSAStartup Failed");
    }
    ~WSASession()
    {
        WSACleanup();
    }
private:
    WSAData data;
};

class UDPSocket
{
public:
    UDPSocket()
    {
        sock = socket(AF_INET,IPPROTO_UDP);
        if (sock == INVALID_SOCKET)
            throw std::system_error(WSAGetLastError(),"Error opening socket");
    }
    ~UDPSocket()
    {
        closesocket(sock);
    }

    void SendTo(const std::string& address,unsigned short port,const char* buffer,int len,int flags = 0)
    {
        sockaddr_in add;
        add.sin_family = AF_INET;
        add.sin_addr.s_addr = inet_addr(address.c_str());
        add.sin_port = htons(port);
        int ret = sendto(sock,len,flags,reinterpret_cast<SOCKADDR *>(&add),sizeof(add));
        if (ret < 0)
            throw std::system_error(WSAGetLastError(),"sendto Failed");
    }
    void SendTo(sockaddr_in& address,int flags = 0)
    {
        int ret = sendto(sock,reinterpret_cast<SOCKADDR *>(&address),sizeof(address));
        if (ret < 0)
            throw std::system_error(WSAGetLastError(),"sendto Failed");
    }
    sockaddr_in RecvFrom(char* buffer,int flags = 0)
    {
        sockaddr_in from;
        int size = sizeof(from);
        int ret = recvfrom(sock,reinterpret_cast<SOCKADDR *>(&from),&size);
        if (ret < 0)
            throw std::system_error(WSAGetLastError(),"recvfrom Failed");

        // make the buffer zero terminated
        buffer[ret] = 0;
        return from;
    }
    void Bind(unsigned short port)
    {
        sockaddr_in add;
        add.sin_family = AF_INET;
        add.sin_addr.s_addr = htonl(INADDR_ANY);
        add.sin_port = htons(port);

        int ret = bind(sock,"Bind Failed");
    }

private:
    SOCKET sock;
};

服务器

#include "Network.h"

int main()
{
    try
    {
        WSASession Session;
        UDPSocket Socket;
        char buffer[100];

        Socket.Bind(100);
        while (1)
        {
            sockaddr_in add = Socket.RecvFrom(buffer,sizeof(buffer));

            std::string input(buffer);
            std::reverse(std::begin(input),std::end(input));
            Socket.SendTo(add,input.c_str(),input.size());
        }
    }
    catch (std::system_error& e)
    {
        std::cout << e.what();
    }
}

客户

#include "Network.h"

int main()
{
    try
    {
        WSASession Session;
        UDPSocket Socket;
        std::string data = "hello world";
        char buffer[100];

        Socket.SendTo("127.0.0.1",100,data.c_str(),data.size());
        Socket.RecvFrom(buffer,100);
        std::cout << buffer;
    }
    catch (std::exception &ex)
    {
        std::cout << ex.what();
    }
    char c;
    std::cin >> c;
}

相关文章

本程序的编译和运行环境如下(如果有运行方面的问题欢迎在评...
水了一学期的院选修,万万没想到期末考试还有比较硬核的编程...
补充一下,先前文章末尾给出的下载链接的完整代码含有部分C&...
思路如标题所说采用模N取余法,难点是这个除法过程如何实现。...
本篇博客有更新!!!更新后效果图如下: 文章末尾的完整代码...
刚开始学习模块化程序设计时,估计大家都被形参和实参搞迷糊...