2009-12-21 103 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++(在我的硬件上)是小端。小问题,但花了一段时间找出这个业余爱好者。

相关问题