作为一个包围我的头围绕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;
- }