我作为 Unix 程序员已经有相当长的时间了,我非常了解系统的套接字 API,我主要将它用于网络。
问题是我目前正在尝试创建一个跨平台软件,因此我开始学习如何将我的源代码编译成 Windows 可执行文件。
我创建了一个 startup() 函数,它执行最简单的操作:连接到服务器(已提供 IP),并在失败时返回 -1。在 Linux 上,我的代码运行流畅,但在 Windows(7) 上,我在某些机器上遇到了同样的错误——“Connect()”函数失败,错误号:“结果太大”,这(据我所知)意味着它找不到任何该 IP 上的监听服务器,但在其他 IP 上运行良好。
这是代码(win 版):
#define _WIN32_WINNT 0x0501
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <windows.h>
#include <winsock.h>
#define ADDR "127.127.127.127"
#define PORT 8752
int startup(struct sockaddr_in sin)
{
int sockfd, soaddr;
WSADATA wsaData;
if (WSAStartup(MAKEWORD(1,1), &wsaData) != 0) {
fprintf(stderr, "WSAStartup failed.\n");
exit(1);
}
if((sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1)
{
fprintf(stderr, "socket:%s\n", strerror(errno));
return(-1);
}
soaddr = sizeof(sin);
if(connect(sockfd, (struct sockaddr*)&sin, soaddr) == -1)
{
fprintf(stderr, "connect:%s\n", strerror(errno));
return(-1);
}
return sockfd;
}
int main(int argc, char *argv[])
{
int sockfd;
struct sockaddr_in sin;
memset(&sin, 0, sizeof(sin));
sin.sin_family = AF_INET;
sin.sin_port = htons(PORT);
sin.sin_addr.s_addr = inet_addr(ADDR);
sockfd = startup(sin);
// Code continues
return(0);
}
注意:出于隐私原因,ADDR 已更改,但该机器上有一个工作服务器
那么,为什么我会收到此错误?
最佳答案
WinSock 不使用 errno
,而是使用 WSAGetLastError()
。
WinSock 不使用套接字的文件描述符,它使用实际的内核对象。在 Windows 上,您需要为套接字变量使用 SOCKET
句柄类型,而不是 int
(或者至少将 SOCKET
值类型转换为(u)intptr_t
,然后在调用 WinSock 函数时类型转换回 SOCKET
。
您可以使用 Win32 API FormatMessage()
函数获取 WinSock 错误代码的人类可读字符串。
#define _WIN32_WINNT 0x0501
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <windows.h>
#include <winsock.h>
#define ADDR "127.127.127.127"
#define PORT 8752
__declspec(thread) char errmsg[256];
char* sockerr(int errcode)
{
DWORD len = FormatMessageA(FORMAT_MESSAGE_ARGUMENT_ARRAY | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, errcode, 0, errmsg, 255, NULL);
if (len != 0)
errmsg[len] = 0;
else
sprintf(errmsg, "error %d", errcode);
return errmsg;
}
int startup()
{
WSADATA wsaData;
int ret = WSAStartup(MAKEWORD(1,1), &wsaData);
if (ret != 0) {
fprintf(stderr, "WSAStartup:%s\n", sockerr(ret));
return(ret);
}
return(0);
}
void cleanup()
{
WSACleanup();
}
SOCKET connectToServer(struct sockaddr_in sin)
{
SOCKET sockfd;
int soaddr;
sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (sockfd == INVALID_SOCKET)
{
fprintf(stderr, "socket:%s\n", sockerr(WSAGetLastError()));
return(INVALID_SOCKET);
}
soaddr = sizeof(sin);
if (connect(sockfd, (struct sockaddr*)&sin, soaddr) == -1)
{
fprintf(stderr, "connect:%s\n", sockerr(WSAGetLastError()));
closesocket(sockfd);
return(INVALID_SOCKET);
}
return(sockfd);
}
int main(int argc, char *argv[])
{
SOCKET sockfd;
struct sockaddr_in sin;
memset(&sin, 0, sizeof(sin));
sin.sin_family = AF_INET;
sin.sin_port = htons(PORT);
sin.sin_addr.s_addr = inet_addr(ADDR);
if (startup() != 0) {
exit(1);
}
sockfd = connectToServer(sin);
if (sockfd != INVALID_SOCKET)
{
// ...
closesocket(sockfd);
}
cleanup();
return(0);
}
在编写跨平台套接字代码时,您必须考虑这些差异。
关于C - 套接字 - 连接 :result too large (windows),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30738046/