C - 套接字 - 连接:结果太大(窗口)

时间:2015-06-09 16:41:11

标签: c windows sockets networking

我是一名Unix程序员已经有相当长的时间了,而且我非常了解系统的套接字API,我主要用于网络。

问题是我目前正在尝试创建一个跨平台的软件,所以我开始学习如何将我的源代码编译成Windows可执行文件。

我创建了一个startup()函数,它执行最简单的操作:连接到服务器(给出IP),并在失败时返回-1。在Linux上,我的代码运行顺畅,但在Windows(7)上,我在某些机器上遇到同样的错误 - " Connect()"功能失败,错误:"结果太大" (根据我的理解)意味着它无法在该IP上找到任何监听服务器,但在其他IP上运行良好。

以下是代码(获胜版本):

#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已更改,但该计算机上有一个正常工作的服务器

那么,为什么我得到这个错误?

2 个答案:

答案 0 :(得分:2)

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);
}

在编写跨平台套接字代码时,您必须考虑这些差异。

答案 1 :(得分:0)

根据您的代码,您在Windows机器上运行client socket。您需要为Windows加载运行时库

#pragma comment (lib, "Ws2_32.lib")
#pragma comment (lib, "Mswsock.lib")
#pragma comment (lib, "AdvApi32.lib")

您可以参考Windows Client Socket Source。希望这对你有用。