C - 套接字 - 连接 :result too large (windows)

标签 c windows sockets networking

我作为 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/

相关文章:

c - 程序输出不稳定?

windows - 将当前文件夹添加到reg文件

c++ - 使用 Berkeley 套接字进行多路复用

java - 安卓 : Keep socket open to read message from server

c - C中数组初始化错误

c - 带有 SIMD 的 vector 的点积

c - 如何从 C 文件中读取最后 n 行

c++ - 从记事本进程内存中读取文本

c - 从适配器获取 DNS 服务器 IP 地址?

sockets - 验证多播端口范围