2014-11-02 208 views
1

我正在寫一個文件共享程序,它的主旨是有一個主服務器,所有客戶端連接到。但是,客戶端是託管文件的機器,因此當一個客戶端從另一個客戶端請求文件時,它必須與它建立連接。當客戶端最初與主服務器連接,我得到它的IP和端口(我認爲)有:獲取客戶端IP地址和端口?

int client_len = sizeof(client); 
    int new_sd = accept(sd, (struct sockaddr *)&client, &client_len); 

    char str[INET_ADDRSTRLEN]; 
    inet_ntop(AF_INET, &(client.sin_addr), str, INET_ADDRSTRLEN); 
    //printf("%s\n", str); 
    int port = (int) ntohs(client.sin_port);   
    //printf("Port is: %d\n", (int) ntohs(client.sin_port)); 

的printf的的給我127.0.0.1和40XXX。主服務器使用127.0.0.1和端口3000.所以我很確定我有正確的客戶端IP和端口但是當我嘗試在兩個使用127.0.0.1和40XXX的客戶端之間建立連接時,它不起作用。連接功能不斷返回一個錯誤。這裏的代碼試圖建立兩個客戶端之間的連接:

if ((cd = socket(AF_INET, SOCK_STREAM, 0)) == -1) { 
    fprintf(stderr, "Can't creat a socket\n"); 
     exit(1); 
    } 
    bzero((char *)&cServer, sizeof(struct sockaddr_in)); 
    cServer.sin_family = AF_INET; 
    cServer.sin_port = htons(cPort); 
    if (inet_pton(AF_INET, cAddress, &cServer.sin_addr) == -1) { 
     printf("inet_pton error occured\n"); 
     exit(1); 
    } 

    /* Connecting to the server */ 
    if (connect(cd, (struct sockaddr *)&cServer, sizeof(cServer)) == -1) { 
     fprintf(stderr, "Can't connect to server\n"); 
     exit(1); 
    } 

cPort是一個int而cAddress是一個char數組。

以下是客戶端嘗試爲傳入連接創建連接的代碼。獲取IP地址和端口的代碼分別返回0.0.0.0和0。

if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) { 
    fprintf(stderr, "Can't creat a socket\n"); 
    exit(1); 
} 

/* Bind an address to the socket */ 
bzero((char *)&clientServer, sizeof(struct sockaddr_in)); 
clientServer.sin_family = AF_INET; 
clientServer.sin_port = 0; 
clientServer.sin_addr.s_addr = htonl(INADDR_ANY); 
if (bind(sockfd, (struct sockaddr *)&clientServer, sizeof(clientServer)) == -1){ 
    fprintf(stderr, "Can't bind name to socket\n"); 
    exit(1); 
} 

char str[INET_ADDRSTRLEN]; 
inet_ntop(AF_INET, &(clientServer.sin_addr), str, INET_ADDRSTRLEN); 
printf("%s\n", str); 
int clientServerPort = (int) ntohs(clientServer.sin_port);  
printf("Port is: %d\n", (int) ntohs(client.sin_port)); 

/* queue up to 10 connect requests */ 
listen(sockfd, 10); 

所有幫助非常感謝!

回答

1

您不能將客戶端端口用於新連接。該端口僅用於連接到您的服務器,它不會偵聽傳入的連接。客戶端需要綁定另一個端口,在其上偵聽並將該端口號發送給您。然後您可以將其發送到另一個客戶端,並且可以連接到該端口。

還要注意,如果第一個客戶端位於NAT路由器後面,這可能根本不起作用。路由器不知道它應該將這個新端口轉發給客戶端。當涉及到NAT時,使用動態端口號的對等應用程序是不切實際的。相反,您應該爲此定義一個專用端口;那麼用戶可以在其路由器上爲此端口配置端口轉發。

+0

這就是我最初的嘗試。使用上面相同的代碼獲取綁定後的IP地址和端口號,但它返回0.0.0.0和0.我更新了我的主帖。即使我嚴格遵守本地IP,NAT路由器也會影響我嗎? – user2929779 2014-11-02 05:58:40

+0

如果你要通過路由器,NAT只是一個問題。如果所有機器都在路由器後面,這不是問題。 – Barmar 2014-11-02 06:00:43

+0

您需要調用'getsockname()'來獲取通過'bind()'分配給套接字的IP和端口。 http://stackoverflow.com/questions/10167540/how-to-get-local-ip-and-port-in-unix-socket-programming – Barmar 2014-11-02 06:02:14