0

c# Use tcp socket Send message to Android:

string data = "my message....";
byte[] msg = Encoding.UTF8.GetBytes(data);
//for example msg Length is 5210 bytes
client.socket.SendBufferSize = 500000;
socket.Send(msg, msg.Length, SocketFlags.None);

Android receive message from c# server-side:

    socket = new Socket(ServerIP, ServerPort);
    socket.setReceiveBufferSize(500000);
    isReceive = true;
    receiveThread = new ReceiveThread(socket);
    receiveThread.start();

private class ReceiveThread extends Thread{
private InputStream inStream = null;
ReceiveThread(Socket socket){
inStream = socket.getInputStream();
}
@Override
public void run(){
while(isReceive){
byte[] buffer = new byte[99999];
try {
//only receive 2896 bytes?
int size = inStream.read(buffer);
} catch (IOException e) {
unConnSocket();
}
}
}
}

why the size only receive 2896 bytes?

tshepang
  • 12,111
  • 21
  • 91
  • 136
Oceansblue
  • 23
  • 5

2 Answers2

1

Your Android code has no way of knowing how many bytes the C# code is sending. inStream.read() is reading only the bytes that are currently available on the socket at that moment. You should have the C# code send the string length before sending the string data, so that the Android code knows how many bytes to expect, eg:

string data = "my message....";
byte[] dataBytes = Encoding.UTF8.GetBytes(data);
int dataLen = IPAddress.HostToNetworkOrder(dataBytes.Length);
byte[] dataLenBytes = BitConverter.GetBytes(dataLen);
socket.Send(dataLenBytes);
socket.Send(dataBytes);

private class ReceiveThread extends Thread
{
    private DataInputStream inStream = null;

    ReceiveThread(Socket socket)
    {
        inStream = new DataInputStream(socket.getInputStream());
    }

    @Override
    public void run()
    {
        while (isReceive)
        {
            try
            {
                String s;
                int size = inStream.readInt();
                if (size > 0)
                {
                    byte[] buffer = new byte[size];
                    inStream.readFully(buffer); 
                    s = new String(buffer, "UTF-8");
                }
                else
                    s = "";

                // use s as needed ...
            }
            catch (IOException e)
            {
                unConnSocket();
            }
        }
    }
}
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
0

Because TCP is a byte stream protocol and isn't obliged to deliver you more than one byte at a time.

You have to loop.

I quote from Linux man recv(2):

The receive calls normally return any data available, up to the requested amount, rather than waiting for receipt of the full amount requested.

user207421
  • 305,947
  • 44
  • 307
  • 483
  • Actually for TCP it's a segment stream based protocol further limited by the MTU.... The stack recieves Ethernet and then parses IP in MTU just like UDP... The stack parses the segments and when complete the application is eligible to receive data from the segment up to the whole segment or whatever is available in the application buffer. If multiple segments are available in TCP then you can and normally will recieve all the data within all the reconstructed segments as contrary to UDP where you only can recieve the single reconstructed segment. – Jay Jul 05 '16 at 23:32
  • 1
    @Jay It is unversally defined as a byte-stream protocol. There are segments underneath but they are not specified to be respected by either the send or the receive functions, and this is the explanation for the behaviour the OP is observing. There is nothing in your comment that invalidates this answer. – user207421 Jul 06 '16 at 00:20
  • Then how would you get only 1 byte if the `segment` has more than 1 byte and you called `recv` with an amount greater than 1? There must have been a segment or a re-transmission which corresponds to the 1 byte for the application layer to receive 1 byte... I know because I use 0 sized packets frequently to indicate various things to legacy protocol senders and recievers where they cannot receive new protocol data. You would also be able to use OutOfBand data but the semantic is the same as the TCP header is still transmitted. How does this not invalidate your answer? – Jay Jul 06 '16 at 04:47
  • @Jay I didn't say you would only get one byte if the segment contained more than one byte. Don't put words into my mouth. I am referring to the contract of *recv(2)* which says exactly what I have stated above. You cannot send (nor therefore receive) zero-length segments in TCP, so I fail to see the relevance, let alone how it can possibly invalidate my answer. You will search the text books in vain for the statement. 'TCP is a segment-oriented protocol', and you will find the statement 'TCP is a byte-oriented protocol' everywhere. It isn't a controversial statement. – user207421 Jul 06 '16 at 05:55
  • @ EJP, ` isn't obliged to deliver you more than one byte at a time` it isn't obliged to give you anything more than you ask for with receive... what you get is a totally different story. (You can get also get `-1`) Finally YES you can send 0 size TCP segments. The receiver end up seeing a 0 length segment depending on the stack in use and how it handles that. You can also use OutOfBand TCP Data but that's a separate data stream. So what, about the citation.. maybe you should stop reading about programming and start actually programming... – Jay Jul 06 '16 at 14:48
  • @Jay If you can't tell the difference between 'isn't obliged to' and 'won't', I can't help you further. I remain unable to see the relevance of this digression about zero length packets, and I am also unable to see how TCP can possibly send one, or how `recv()` can possibly receive it and pass it to the application while adhering to its contract which I have stated in the answer. It would have to return a zero length, which already means end of stream. Are you thinking of UDP? – user207421 Jul 06 '16 at 20:05
  • 0 result from recv does not mean end of stream, that's where your wrong again. It means a segment of 0 size or there is no data available, the stack can choose to report 0 or just ignore it totally and the semantic is the same. It is ackd, If your socket is non blocking or the recieve times out that's also up to the stack but the value is usually a value of -1 in those cases but may not be. This the same for TCP and UDP or IP, your misconception seems to be on how Socket implementations vary and then further on how ethernet becomes tcp, udp or whatever other protocols the application is using. – Jay Jul 06 '16 at 20:31
  • The point stands, tcp is obliged to honor the amount passed 'recv', udp does not. This answer stating anything about one byte is wrong unless you pass 1 to recv or you get a 0 or 1 byte sized segment. – Jay Jul 06 '16 at 20:40
  • Please read *man recv(2)* thoroughly before posting any more of this nonsense. End of stream is exactly what zero means on a TCP socket, and the contract of `recv()` in blocking mode is that it blocks until at least one byte has been transferred or end of stream or an error occurs. Specifically, it is not obliged to fill the buffer, and this is what explains the OP's problem. If you were correct, he wouldn't *have* a problem. You don't appear to know the first thing about it, and you haven't cited a single source in support of your claims. – user207421 Jul 06 '16 at 21:05
  • Wow, nonsense eh? What about recv should I be looking at specifically? Your books are nonsense and your reasoning is only trumped by your confidence which is misplaced in time. I find no merit to argue further when the results are clear, if I send a tcp packet with 0 bytes an IP header is also sent and an ethernet packet. The ethernet packets contains the IP header and the payload which is a tcp header which defined a 0 length segment. This is not End Of Stream, and I can clearly still recieve on this socket after the point at which I get a timeout or a 0 value on recieve from the application – Jay Jul 06 '16 at 21:12
  • Perhaps you need an example of the 0 byte reception or otherwise proof that your wrong? I have software you can download and try this out if you can't write a simple app to test it yourself. I could also provide you wireshark captures... FYI this mechanism is similar to how don't fragment is abused to allow bypassing firewalls. None the less if your os and stack have some configuration where 0 sized segments means EOS only then I would concede to your point and not at the TCP protocol level because it's still wrong but at the stack / driver level and not as the 'norm' therefor man won't help. – Jay Jul 06 '16 at 21:17
  • Maybe you can cite this comment once you inevitably revise your thinking again.... – Jay Jul 06 '16 at 21:18
  • @Jay *man recv(2)*: 'Return Value: These calls return the number of bytes received, or -1 if an error occurred. The return value will be 0 when the peer has performed an orderly shutdown' and 'If no messages are available at the socket, the receive calls wait for a message to arrive, unless the socket is nonblocking (see *fcntl(2)*), in which case the value -1 is returned and the external variable `errno` is set to EAGAIN or EWOULDBLOCK. The receive calls normally return any data available, up to the requested amount, rather than waiting for receipt of the full amount requested'. – user207421 Jul 06 '16 at 23:58
  • That's for sockets in general, TCP and UDP data are formed from the same network traffic PDU which contains an IP header. If that IP payload is complete then the application can recieve the data under udp, under tcp only the data acknowledged in the data portion of the TCP portion of the IP packet is able to be recv. If that amount if 0 then the stack will ack 0 and the application will possibly recieve the 0 value and must poll the socket to determine if shutdown was performed in such situations. – Jay Jul 07 '16 at 00:31
  • @Jay Not content with insulting my work and introducing a totally extraneous matter into this discussion, you are now arguing with the *man* pages and with an answer that agrees with them. I don't know what your problem is but please take it somewhere else. If what you were claiming here about the irrelevant matter of zero-length segments was correct it would be impossible for an application to distinguish between that and a peer disconnection. It simply is not so, and it remains irrelevant to this answer. – user207421 Jul 07 '16 at 00:59
  • I am not arguing with it, I said basically the same thing off the top of my head and only accidentally transposed tcp and udp in a single comment. You however again swear what has relevance and what doesn't but again that lacks merit due to your bias and false self confidence. – Jay Jul 07 '16 at 10:38
  • Further for being a so pendentic that you can't admit when your wrong.... e.g. just like in the IP header discussion where u claim the IP and tcp headers are fixed length, argue that your right and bail. This time you cite a man page on sockets to prove a point about tcp and protocol implementation... and you say my banter is nonsense... what's the topic here sockets api semantic or protocol api semantic and who gives u the right to decide?.... – Jay Jul 07 '16 at 10:54