2017-10-17 85 views
1

我懷疑這有一個簡單的解決方案,我忽略了,可能與客戶端或如何設置。
無論如何,我試圖建立一個簡單的Echo服務器/客戶端來了解套接字編程的基礎知識。我有一臺運行Linux Mint的虛擬機,主機運行的是Windows 10.我設置的虛擬機運行服務器c代碼,Windows將運行客戶端。連接到本地虛擬機

我開始做服務器代碼

//Echo Server for UNIX: Using socket programming in C, a client sends a string 
//to this server, and the server responds with the same string sent back to the client 

#include <stdio.h> 
#include <sys/socket.h> 
#include <sys/types.h> 
#include <netinet/in.h> 
#include <arpa/inet.h> 
#include <unistd.h> 
#include <string.h> 

int main() 
{ 
    char stringBuffer[50]; //string buffer for reading incoming and resending 
    int listener, communicator, c; //store values returned by socket system call 

    if((listener = socket(AF_INET, SOCK_STREAM, 0)) == -1) //creates a new socket 
     puts("Could not create socket"); 
    puts("Socket Created"); 

    struct sockaddr_in servAddr, client; //structure from <netinet/in.h> for address of server 
    servAddr.sin_family = AF_INET; //addressing scheme set to IP 
    servAddr.sin_port = htons(8888); //server listens to port 5000 
    servAddr.sin_addr.s_addr = inet_addr("127.0.0.1"); //symbolic constant of server IP address 

    //binds the socket to the address of the current host and port# the server will run on 
    if (bind(listener, (struct sockaddr *) &servAddr, sizeof(servAddr)) < 0){ 
     puts("Bind failed"); 
     return 1; 
    } 
    puts("Bind Successful"); 

    listen(listener, 5); //listens for up to 5 connections at a time 
    c = sizeof(struct sockaddr_in); 
    if ((communicator = accept(listener, (struct sockaddr*)&client, (socklen_t*)&c))<0) 
     puts("accept failed"); 
    puts("Connection Accepted"); 
    //wait until someone wants to connect, then whatever is sent can be read from communicator, which can then be sent back 

    while(1){ 
     bzero(stringBuffer, 50); //sets buffer to 0 
     read(communicator, stringBuffer, 50); //reads from communicator into buffer 
     write(communicator, stringBuffer, strlen(stringBuffer)+1); //returns back 
    } 
    return 0; 
} 

之後,我測試了它在客戶機打開另一個終端和類型「遠程登錄本地主機8888」,並輸入我想任何字符串。

這個測試已經摸索的話,到我的Windows機器上創建的socket編程的客戶端:現在

#include <winsock.h> 
#include <stdio.h> 
#include <string.h> 
#pragma comment(lib,"ws2_32.lib") //Winsock Library 

int main(int argc, char *argv[]) 
{ 

    WSADATA wsadata; //variable for using sockets in windows 
    SOCKET sock; //socket variable for network commands 
    char sendString[50], recieveString[50]; //variables for sending and recieving messages to/from server 

    //check if WSA initialises correctly 
    if (WSAStartup(MAKEWORD(2,2), &wsadata) != 0) 
     printf("Error Code: %d", WSAGetLastError()); 

    //creates new socket and saves into sock 
    if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET) 
     printf("Could not create socket: %d", WSAGetLastError()); 
    printf("Socket created\n"); 

    struct sockaddr_in servAddr; 
    servAddr.sin_addr.s_addr = inet_addr("127.0.0.1"); //sets the IP address to the same machine as the server 
    servAddr.sin_family = AF_INET; //addressing scheme set to TCP/IP 
    servAddr.sin_port = htons(8888); //server address is on port 8888 

    //connects to device with specifications from servAddr 
    if (connect(sock, (struct sockaddr *)&servAddr, sizeof(servAddr)) < 0) { 
     printf("Connection Error %d\n", WSAGetLastError()); 
     return 1; 
    } 
    printf("Connection Accepted\n"); 

    while(1){ 
     fgets(sendString, 50, stdin); //uses stdin to get input to put into sendString 
     //sends sendString to server using sock's properties 
     if (send(sock, sendString, strlen(sendString) + 1, 0) < 0); { 
      printf("Send Failed"); 
      return 0; 
     } 

     //reads from server into recieveString 
     if ((recv(sock, recieveString, 50, 0)) == SOCKET_ERROR) 
      printf("Recieve Failed"); 
     printf("%s", recieveString); //prints out recieveString 
    } 
} 

,與服務器仍在運行,當我嘗試了客戶端,我得到響應「連接錯誤」(來自第35行)。看了Unix和WinSock的例子,我不確定爲什麼我會失敗連接。我懷疑它可能與Windows到Linux虛擬機有關,但我不確定。

--- UPDATE --- 更新了意外分號並添加了WSAGetLastError後,顯示的錯誤代碼爲10061;這將轉換爲 「連接被拒絕 由於目標計算機主動拒絕連接,因此嘗試連接到外部主機上處於非活動狀態的服務(即沒有運行服務器應用程序的服務)會導致無法建立連接。 「

+2

if語句後爲什麼會有分號?第34行 – Kishor

+0

'c'應該是'socklen_t' * not *'int'! – alk

+0

你*在同一個盒子上運行服務器和客戶端,不是嗎? – alk

回答

3

[第三次編輯後:]

Sry,只是重新讀你的問題。重要的是這裏:

我設置的虛擬機運行服務器c代碼,並且Windows將運行客戶端。

127.0.0.1是一個地址總是只是本地到支持IP框。因此,您的服務器正在偵聽Linux虛擬機本地的接口127.0.0.1,並且客戶端嘗試連接到Windows本地的127.0.0.0。那兩個接口是不是一樣。結果很明顯,即客戶端找不到任何連接。

127.0.0.1(即所謂的 「IPv4的本地迴環interfac E」)只能用於連接當地準確一個框。

+0

好吧,回答爲什麼,問題將是什麼知識產權我使用那麼? – RELENTLESS00G

+0

服務器主機的錯誤IP? – EJP

+0

也就是說,我也嘗試使用INADDR_ANY服務器,但客戶端發送到哪個IP? - 編輯:好吧,他們真的在網絡上看到彼此完全不同的東西嗎?我不確定IP地址是如何真正用於訪客機器的,對不起 – RELENTLESS00G

3
if (connect(sock, (struct sockaddr *)&servAddr, sizeof(servAddr)) < 0); { 
    printf("Connection Error"); 
    return 1; 
} 

這只是一個微不足道的語法錯誤。您無條件地進入該塊。刪除第一個分號。

然而,還有一個更重要的要點。當您從系統調用(如connect())中收到錯誤時,必須打印的錯誤。不只是你自己設計的一些信息。否則,你不知道你是否有一個錯誤,或一個暫時的問題,或一個長期的問題,或一個永久的問題。

更改printf()到:

printf("Connect error %s\n", WSAGetLastError()); 

然後繼續如同錯誤沒有發生。

注意,這適用於所有系統來電,具體包括socket()bind()listen()connect()accept()recv()send(),和朋友。

+0

對不起,我忽略了分號,但它確實不是問題所在。不知道爲什麼我忘記了該行的WSAGetLastError(),但沒有其他的,謝謝你指出。我已經更新了當前的錯誤代碼和翻譯。 – RELENTLESS00G

+1

這真的是*問題。現在的問題是WSAECONNREFUSED,它僅僅意味着在您嘗試連接的IP:端口上沒有任何監聽。 – EJP

+0

在我作出條件陳述以查明問題出在哪裏之前,它沒有奏效;這是一個問題,但只是在檢查問題出在哪裏時才引入。現在的問題是,爲什麼會出現這種錯誤?在我的服務器中有一個在該IP的監聽器:端口 – RELENTLESS00G