2015-06-09 25 views
0

我去過一個Unix程序員的時間像樣的數目,我知道得很好系統的插座API,我用它主要用於網絡。Ç - 插座 - 連接:造成太大(窗口)

的事情是,我正在試圖建立一個跨平臺的軟件,所以我開始學習如何編譯我的源代碼到Windows可執行文件。

我創建了一個啓動()函數做最簡單的事情:連接到服務器(其中IP給出),並返回-1失敗。在Linux上,我的代碼運行平穩,但在Windows(7)上,我在某些機器上得到了同樣的錯誤 - 「Connect()」函數失敗,errno:「結果太大」(根據我的理解)意味着它找不到任何在該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已更改隱私的原因,但有這臺機器上工作的服務器

那麼,到底爲什麼我收到這個錯誤?

+1

我不確定WSA的'socket'函數是否改變了'errno'。 'errno'是一個C/C++運行時庫工件,系統API函數不太可能對其進行更改。 [文檔](https://msdn.microsoft.com/en-us/library/windows/desktop/ms737625%28v=vs.85%29.aspx)指定您需要調用'WSAGetLastError'來獲取錯誤代碼。 – ach

+1

WinSock根本不使用'errno'。 'WSAGetLastError()'(在某些情況下,'getsockopt(SO_ERROR)')是我看到的WinSock錯誤代碼 –

回答

0

根據你的代碼在Windows上運行client socket machine.You需要加載運行時庫Windows作爲

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

你可以參考Windows Client Socket Source。希望這對你有用。

+0

的方法,但事情是:程序可以工作,但在某些機器上它不會它確實可以阻止通信的防火牆嗎? – Alfaso

+0

是的,你需要禁用你的防火牆。在Windows上運行Server Socket時遇到防火牆問題。嘗試禁用防火牆 –

1

的WinSock不使用errno,它使用WSAGetLastError()代替。

的WinSock不使用文件描述符插座,它採用實際的內核對象。在Windows中,您需要使用SOCKET手柄式,不int,爲您的插座變量(或至少型鑄造SOCKET(u)intptr_t,然後調用的WinSock函數時類型強制轉換回SOCKET)。

您可以使用Win32 API函數​​得到了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); 
} 

編寫跨平臺套接字代碼時,您將不得不考慮這些差異。