2

I make a java socket server and c socket client, here are the code

Java Socket Server:

int Send_Request(String s) {

    try {
        os = socket.getOutputStream();
        os.write(s.getBytes());
        os.flush();

        Log.d(tag,"Data = " + s);

        return 0;
    } catch (IOException e) {
        // TODO Auto-generated catch block
        Log.e(tag,"Send Request Error");
        return -1;
    }

C socket client:

void* recv_request()
{
int i,in;
char buf[1024];
while(1)
{
    if ( ( in = read(sockfd, buf, strlen(buf)) ) != -1 )
    {
        LOGD("Received = %s ...",buf);
        sendServerCutText(buf);
        memset(buf,0,strlen(buf));
    }

}

}

The problem is .. when i send from the server, it is blocking on flush(), the c client cannot receive until there is another Send_Request called.

where is the problem??

vonc
  • 65
  • 3
  • 8
  • 3
    You can't call `strlen(buf)` unless `buf` contains a C-style string. You're receiving arbitrary binary data, not C-style strings. And you even call `strlen` before you have any data at all! – David Schwartz Apr 08 '12 at 08:27

1 Answers1

3

There is a conceptual problem. You think TCP is message oriented (sending messages with specified length). It's not like that, it is only providing a stream of bytes.

For sending a message with a specified length a common technique is to send first the length (encoded in fixed length, eg 4 byte integer in network byte order) and then the actual message.

There's also an implementation problem, the 3rd argument for read should be the maximum read length, which should be 1024, executing strlen on a non-initialized local char array is clearly undefined-behaviour.

Karoly Horvath
  • 94,607
  • 11
  • 117
  • 176
  • 1
    If the length is not known before sending, or the message format has to be textual, it is also possible to send a special byte- or character-sequence as a separator between messages. For protocols like telnet the linebreak is a natural message separator. – Some programmer dude Apr 08 '12 at 08:33
  • and HTTP uses string representation of the length. – Karoly Horvath Apr 08 '12 at 08:37
  • is it right for me to add os.write(s.length()); before os.write(s.getBytes()), and then first read(sockfd, buflen, 4), then read again with read(sockfd, buf, ??? )? – vonc Apr 08 '12 at 09:03
  • `os.write(s.length());` - if the endianness of the server and client machine is the same, then yes, otherwise you have to enforce the endianness... (eg: http://stackoverflow.com/questions/9129391/inet-ntoa-and-inet-aton-in-java ). 2) yes, first read the length, then on the next call use that length. – Karoly Horvath Apr 08 '12 at 17:06
  • i have changed the s.length() to a 4 bytes integer and then send via os.write(intToBytesArray(s.length())), and the c client read(sockfd, buf_len, 4), but it still blocking on the os.write(), what is the problem i wrote? – vonc Apr 08 '12 at 19:49
  • hard to tell.. it should work. please post a full minimalistic example which reproduces the problem. – Karoly Horvath Apr 08 '12 at 21:07
  • [Socket.java](https://docs.google.com/open?id=0Bw4pNkNcAT9mWE9ydG52NWdTYzZ6N3VkYk8zREhvUQ), [Socket.c](https://docs.google.com/open?id=0Bw4pNkNcAT9mOFBIY0cxRmhUMmlxazVPMjM1UHo1UQ), here are the file , thanks for helping ! – vonc Apr 09 '12 at 05:15