我一直在尝试用C ++编写一个简单的聊天程序,而且我遇到了socket问题。以下代码返回
上次错误代码为(1):0
最后一个错误代码是(2):0
最后一个错误代码是(3):10049
上一个错误代码是(4):10022
在检查MSDN页面的WSA错误之后,我发现10022用于无效参数,而10049试图绑定到不可用的地址。我断定10049错误导致10022错误,因为我试图侦听未绑定的套接字。
之后,尝试了几个不同的地址来查找任何可用的地址,包括127.x.x.x,192.168.x.x,0.0.0.0,其中没有一个有效。我跳进CMD,看到其他进程正在使用这些地址任何人都指出我正确的方向找到这个问题的根源?
#include "stdafx.h"
using namespace std;
int main()
{
long SUCCESSFUL;
WSAData WinSockData;
WORD DLLVERSION;
DLLVERSION = MAKEWORD(2, 1);
SUCCESSFUL = WSAStartup(DLLVERSION, &WinSockData);
SOCKADDR_IN ADDRESS;
int AddressSize = sizeof(ADDRESS);
SOCKET sock_CONNECTION;
const CHAR addr[15] = "127.0.0.1";
char buffer [sizeof(in_addr)];
printf("Last error code was(1): %d\n", WSAGetLastError());
sock_CONNECTION = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
ADDRESS.sin_addr.s_addr = inet_pton(AF_INET, (const CHAR*)&addr, &buffer);
ADDRESS.sin_family = AF_INET;
ADDRESS.sin_port = htons(444);
printf("Last error code was(2): %d\n", WSAGetLastError());
bind(sock_CONNECTION, (SOCKADDR *)&ADDRESS, AddressSize);
printf("Last error code was(3): %d\n", WSAGetLastError());
listen(sock_CONNECTION, 5);
printf("Last error code was(4): %d\n", WSAGetLastError());
//note to self: don't use %x when referring to WSAGetLastError, returns untrue value outside WSAerror regular field
pause();
return 0;
}
答案 0 :(得分:1)
首先,一般注意事项:您需要检查所调用的每个函数的返回值,并且只有在返回值指示函数返回错误时才打印出WSAGetLastError()的值。否则,您只会通过查看先前调用遗留的错误代码值来混淆自己,并且与最近调用的调用没有任何关系。也就是说,而不是这样做:
bind(sock_CONNECTION, (SOCKADDR *)&ADDRESS, AddressSize);
printf("Last error code was(3): %d\n", WSAGetLastError());
......你应该这样做:
if (bind(sock_CONNECTION, (SOCKADDR *)&ADDRESS, AddressSize) != 0)
{
printf("bind() failed, last error code was(3): %d\n", WSAGetLastError());
}
...和您调用的所有其他功能类似。 (请注意,不同的函数返回不同的值以指示错误,因此您需要阅读每个函数的文档页面,以找出测试成功与失败的返回值的正确方法)
那就是说,我认为具体问题在于:
ADDRESS.sin_addr.s_addr = inet_pton(AF_INET, (const CHAR*)&addr, &buffer);
inet_pton()不会返回地址;相反,如果地址对指定的地址族有效,则返回“1”;如果地址在指定的地址族中不可解析,则返回0;如果发生某些系统错误,则返回-1(在这种情况下,将设置errno)“。因此,您要写入ADDRESS.sin_addr.s_addr的值为-1,0或1;这些都不是bind()想要使用的有效地址。 (好吧,实际上可以使用0;见下文,但调用仍然是错误的)
调用inet_pton()的正确方法更像是:
int result = inet_pton(AF_INET, addr, &ADDRESS.sin_addr);
if (result != 1) printf("inet_pton() failed, error code %d\n", WSAGetLastError());
...但我怀疑你可能想做什么(接受任何网络接口上的连接),你根本不需要调用inet_pton()。相反,您可以将ADDRESS.sin_addr.s_addr设置为INADDR_ANY,然后bind()将绑定您的套接字,使其接受传入的TCP连接,无论它们进入哪个网络接口。
// INADDR_ANY (aka 0) means "I don't care which network interface, accept connections on any of them"
ADDRESS.sin_addr.s_addr = INADDR_ANY;