2009-12-21 143 views
3

我知道這肯定是一個很常見的問題,但我一直無法找到關於如何做的明確答案。Java套接字(服務器)和C++套接字(客戶端)之間的網絡通信

首先,假設我們有一個接受查詢,如Java服務器(我只是把相關的行,我已經取出來了異常處理的清晰度):

ServerSocket socket = new ServerSocket(port); 
    while (true) { 
     ClientWorker w; 
     w = new ClientWorker(socket.accept()); 
     Thread t = new Thread(w); 
     t.start(); 
    } 

,然後在在ClientWorker

BufferedReader inFromClient = new BufferedReader(new InputStreamReader(client.getInputStream())); 
    DataOutputStream outToClient = new DataOutputStream(client.getOutputStream()); 

    String query = inFromClient.readLine(); 
    // process query here 
    String response = "testresponse"; 

    outToClient.writeBytes(response + "\n"); 

    outToClient.close(); 
    inFromClient.close(); 
    client.close(); 

現在,我可以得到一個Java客戶端與此服務器的工作原理:

String query = "testquery"; 
Socket queryProcessorSocket = new Socket(queryIp,queryPort); 
DataOutputStream queryProcessorDos = new DataOutputStream(queryProcessorSocket.getOutputStream()); 
BufferedReader queryProcessorReader = new BufferedReader(new InputStreamReader(queryProcessorSocket.getInputStream())); 
queryProcessorDos.writeBytes(query + "\n"); 
String response = queryProcessorReader.readLine(); 

但是我怎樣才能得到一個C++客戶端來做和java客戶端一樣的事情呢?我嘗試了很多東西,但似乎沒有任何工作。理想情況下,我不想觸摸java服務器,這是可能的嗎?如果有人能指出我一個很好的例子或一些示例代碼,那將非常感激。我搜索了很多網站,但無濟於事。

回答

5

這裏我把一個簡單的代碼連接到服務器。如果這是你的問題,它可能會幫助你。

void client(const char* server_address, short server_port) 
{ 
    int  sockfd; 
    struct sockaddr_in servaddr; 

    sockfd = socket(AF_INET, SOCK_STREAM, 0); 

    memset(&servaddr, 0x00, sizeof(servaddr)); 
    servaddr.sin_family = AF_INET; 
    servaddr.sin_port = htons(server_port); 
    inet_pton(AF_INET, server_address, &servaddr.sin_addr); 

    connect(sockfd, (struct sockaddr *) &servaddr, sizeof(servaddr)); 

    //from this point you can start write to the server and wait for its respose 

    std::string buffer = "testquery"; 
    writen(sockfd, buffer.c_str(), buffer.length()); 

    char *ReadBuffer[512]; 
    while(1) 
    { 
     memset(ReadBuffer, 0x00, sizeof(ReadBuffer)); 
     int n = readn(sockfd, ReadBuffer, sizeof(ReadBuffer)); 
     if(n <= 0) 
     { 
      //or you dont have anything to read, or you have a problem 
      break; 
     } 
     //this function does the hard job of knowing what to do with all these data 
     processBuffer(ReadBuffer, n); 
    } 

close(sockfd); 

} 

我使用POSIX標準,代碼非常簡化,但我認爲它是一個起點。

問候。

+0

很好的例子,雖然你應該記得檢查返回代碼,特別是檢查錯誤代碼。如果發生錯誤,您的循環將結束,並且您不檢查以確保連接成功。在網絡代碼中,絕對有必要知道您的緩衝區中實際上還有多少數據,並且不要以爲這些數據是以null結尾的。另外,多個調用在一端發送可能會導致這些緩衝區被連接起來,這樣您就可以在另一端讀取所有數據。 – 2009-12-22 00:48:25

+0

輕微nitpicky點:有點奇怪,你繼續寫512而不是sizeof(ReadBuffer)。另外,如果read()獲取EINTR? – asveikau 2009-12-22 00:48:45

+0

@Jeff:實際上,通過閱讀代碼示例,我假定processBuffer()將處理錯誤,並可能將任何部分完成的請求分割爲多個讀取到單獨的堆緩衝區,以便在下次讀取時處理。至少,這就是我要做的。 – asveikau 2009-12-22 00:52:47

2

你是什麼意思「它不工作」?

如果不仔細研究代碼,我的第一個擔心就是要將字符串(以字符或字節對形式)轉換爲字節,然後將這些字符串發送到套接字中。你是否在C++端以相同的方式檢索它們?即使用相同的字符編碼?

+0

我會補充說,Java使用Unicode(UTF-16)來存儲一個字符。所以要麼在發送之前將Java String轉換爲ANSI,要麼在C++客戶端使用std :: wstring。 – 2009-12-23 11:16:40

+0

@Adrien - 有價值的點 – 2009-12-23 11:23:31

0

是的,你可以有一個C++客戶端(或一個C客戶端,一個COBOL客戶端或一個perl客戶端或一個紅寶石客戶端或一個客戶端)與一個java服務器交談。你所要做的就是將Java代碼移植到等效的C++代碼(或C代碼或COBOL代碼或Perl代碼或Ruby代碼或...代碼)。服務器既不知道也不關心客戶端編寫什麼語言。

我將從此參考開始Internet Sockets,然後使用POSIX API文檔。

1

只要你不使用語言特定的協議(如Java RMI)並使用直接套接字(或其他一些語言中立協議,如Web服務),那麼它就可以工作。您只需確保您的客戶端和服務器使用相同的協議(例如TCP/IP +您的自定義協議)。如果使用直接套接字,則基本上是通過線路發送二進制文件 - 所以您需要確保在兩側對數據進行編碼/解碼。通常情況下,這是通過某種字節級別的協議完成的,如果你正在自己開發的話。作爲一個例子Project Dark Star是一個用Java編寫的遊戲服務器,但具有Java,C/C++,Flash等的客戶端。它使用用戶定義的二進制協議進行跨語言通信。

0

我以前有同樣的問題。客戶端是基於C++的,它必須連接到我在Windows上運行的基於Java的服務器。爲了讓Java服務器在客戶端連接時斷開連接,我被擱置了很長時間。

後來我意識到這是因爲endian問題。 Java VM =大端,C++(在我的硬件上)是小端。小問題,但花了一段時間找出這個業餘愛好者。

相關問題