从java挂起/块读取c套接字

时间:2013-01-15 12:51:15

标签: java c sockets

我遇到了Java和C之间的套接字问题。我有一个C程序,它创建一个套接字并开始监听。 Java客户端执行它的工作,并在某些情况下打开一个套接字并写入它并尝试从中读取但这会阻塞。

继承C程序的套接字部分:

int sockfd, newsockfd, portno;
socklen_t clilen;
char buffer[256];
char wbuffer[256];
struct sockaddr_in serv_addr, cli_addr;
int n;

sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0)
        cout << "ERROR opening socket" << endl;
bzero((char *) &serv_addr, sizeof(serv_addr));
portno = 23456;
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = INADDR_ANY;
serv_addr.sin_port = htons(portno);
int on = 1;
if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0)
        cout << "Couldn't set socket params!" << endl;
int so = bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr));
while(so < 0) {
        cout << "ERROR on binding" << endl;
        sleep(1);
        so = bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr));
}
listen(sockfd,5);
clilen = sizeof(cli_addr);
newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen);
if (newsockfd < 0)
        cout << "ERROR on accept" << endl;
bzero(buffer,256);
//cout << "Socket created!" << endl;
n = read(newsockfd,buffer,255);
if (n < 0)
        cout << "Error reading from socket" << endl;
 if (strcmp(buffer, "power\n") == 0) {
         // Do stuff
     strcpy(wbuffer, "off\n");
         }
     //sleep(1);
     n = write(newsockfd,wbuffer,strlen(wbuffer));
     if (n < 0)
         cout << "ERROR writing to socket" << endl;
}
//cout << "message: " << buffer << endl;
close(newsockfd);
close(sockfd);

Java方面:

Socket socket3 = new Socket("localhost", 23456);
PrintWriter out3 = new PrintWriter(socket3.getOutputStream(), true);
BufferedReader in = new BufferedReader(new InputStreamReader(socket3.getInputStream()));
out3.write("power" + "\n");
//String status = in.readLine();
log.debug("Wrote power");
StringBuffer buffer = new StringBuffer();
while (true) {
    int ch = in.read();
    log.debug("in.read()");
    if ((ch < 0) || (ch == '\n')) {
        break;
    }
    buffer.append((char) ch);
}
String status = buffer.toString();
out3.close();
in.close();
socket3.close();

写作工作,我做了一些调试,这是阅读,特别是in.read(),这是最后一件事。

我可能在Java方面遗漏了一些东西,因为C测试客户端很好地读取了输出。

希望有人有一些想法如何让这个工作,我愿意接受任何解决方案。

3 个答案:

答案 0 :(得分:2)

您的C ++代码非常糟糕。考虑在read(2)返回少于6的情况下会发生什么。一般而言:

n = read(newsockfd,buffer,255);

if (n < 0)
    cout << "Error reading from socket" << endl;

// continuing processing after an error - BAD

// not paying attention to n - BAD
if (strcmp(buffer, "power\n") == 0) {
     // Do stuff
     strcpy(wbuffer, "off\n");
}

// potentially writing zero bytes here - BAD
n = write(newsockfd,wbuffer,strlen(wbuffer));

if (n < 0)
     cout << "ERROR writing to socket" << endl;

} // WHERE DID THIS PAREN COME FROM?

所以解决这些问题。请查看tcpdump(1)wireshark您在线上获得的内容。双面打印输入。你可能会看到你的假设在某个地方消失了。

答案 1 :(得分:1)

事实证明,问题实际上不是在阅读部分,而是在写作中。我忘了刷新输出所以它实际上没有开始阅读,或者有什么东西要读。添加flush后,读取工作正常,我甚至可以使用readline()来使代码更简单。

我只写入套接字的其他情况有效,因为关闭流时会调用flush,这会让我失望。

C代码很讨厌,我需要清理它并实际处理异常。

感谢大家帮助我,如果没有答案,我会花很长时间才能找到我的错误。

答案 2 :(得分:0)

也许问题是你正在读一个整数:

int ch = in.read()

您是否尝试过将其更改为:

char ch = in.read()

或者在比较之前将整数强制转换为char:

if((char) ch == '\n' || ch < 0)

我现在想不出任何其他事情......