我一直在尝试用C++编写一个简单的聊天程序,但遇到了套接字问题。以下代码返回
最后一个错误代码是(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): %dn", 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): %dn", WSAGetLastError());
bind(sock_CONNECTION, (SOCKADDR *)&ADDRESS, AddressSize);
printf("Last error code was(3): %dn", WSAGetLastError());
listen(sock_CONNECTION, 5);
printf("Last error code was(4): %dn", WSAGetLastError());
//note to self: don't use %x when referring to WSAGetLastError, returns untrue value outside WSAerror regular field
pause();
return 0;
}
首先,一般说明:您需要检查您调用的每个函数的返回值,并且只有在返回值指示函数返回错误时才打印出 WSAGetLastError(( 的值。 否则,您只会通过查看以前调用中遗留的错误代码值来混淆自己,并且与最近调用的调用没有任何关系。 也就是说,而不是这样做:
bind(sock_CONNECTION, (SOCKADDR *)&ADDRESS, AddressSize);
printf("Last error code was(3): %dn", WSAGetLastError());
。你应该这样做:
if (bind(sock_CONNECTION, (SOCKADDR *)&ADDRESS, AddressSize) != 0)
{
printf("bind() failed, last error code was(3): %dn", WSAGetLastError());
}
。以及您调用的所有其他函数的类似功能。 (请注意,不同的函数返回不同的值来指示错误,因此您需要阅读每个函数的文档页面,以找出测试成功与失败返回值的正确方法(
也就是说,我认为具体问题就在这里:
ADDRESS.sin_addr.s_addr = inet_pton(AF_INET, (const CHAR*)&addr, &buffer);
inet_pton(( 不返回地址;而是返回"如果地址对指定的地址系列有效,则返回 1;如果地址在指定的地址系列中不可解析,则返回 0;如果发生某些系统错误(在这种情况下,将设置 errno(则返回 -1"。 因此,您写入 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 %dn", 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;