简体   繁体   English

从Java挂起/块读取C套接字

[英]Reading c socket from java hangs/blocks

I have a problem with sockets between Java and C. I have a C program that creates a socket and starts listening. 我在Java和C之间的套接字有问题。我有一个C程序,它创建一个套接字并开始监听。 The Java client does it's work and under certain circumstances opens a socket and writes to it and tries to read from it but this blocks. Java客户端可以正常工作,并且在某些情况下会打开套接字并对其进行写入,然后尝试从中读取,但是这会阻塞。

Heres the socket part of the C program: 这是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);

And the Java side: 而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();

The writing works, I have done some debugging and it's the reading, specifically in.read(), that is the last thing done. 写作工作已经完成,我已经进行了一些调试,最后要做的就是阅读,尤其是in.read()。

I am probably missing something on the Java side, because a C test client reads the output nicely. 我可能在Java方面缺少一些东西,因为C测试客户端很好地读取了输出。

Hopefully someone has some ideas how to get this working, I'm open to any solutions. 希望有人对如何使它起作用有想法,我愿意接受任何解决方案。

Your C++ code is pretty horrible. 您的C ++代码非常可怕。 Consider what would happen in case read(2) returns less then 6 . 考虑一下read(2)返回小于6情况会发生什么。 And just in general: 一般而言:

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?

So fix those problems. 因此,请解决这些问题。 Check with tcpdump(1) or wireshark what you get on the wire. 使用tcpdump(1)wireshark检查您在网络上得到了什么。 Print out your input on both sides. 双面打印您的输入。 You'll probably see that you assumptions are off somewhere. 您可能会发现您的假设不在某个地方。

Turns out that the problem wasn't actually in the reading part but in the writing. 原来,问题实际上不在阅读部分,而是在写作方面。 I had forgotten to flush the output so it hadn't actually started reading or was there anything to read for that matter. 我忘了刷新输出,所以它实际上并没有开始读取,或者有什么要读取的。 After adding the flush the reading worked just fine, I could even use readline() to make the code simpler. 添加冲洗后,读取效果很好,我什至可以使用readline()简化代码。

The other cases where I only wrote to the socket worked because flush is called when closing the stream, this was throwing me off. 在其他情况下,我只写给套接字的方法起作用,因为在关闭流时调用了flush,这使我失望了。

The C-code is nasty and I need to clean it up and actually handle the exceptions. C代码令人讨厌,我需要清理它并实际处理异常。

Thanks for everyone for helping me anyway, without the answers it would have taken a lot longer to find my mistake. 无论如何,感谢大家为我提供的帮助,如果没有答案,发现我的错误将花费更长的时间。

Maybe the problem is you're reading an Integer: 也许问题在于您正在读取Integer:

int ch = in.read()

Have you tried changing it for: 您是否尝试过将其更改为:

char ch = in.read()

Or having the integer cast to a char before comparing: 或者在比较之前将整数转换为char:

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

I can't think of anything else right now... 我现在想不出什么...

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM