Solved

Socket server sends text, client gets cut off or twisted...Problem with sock recv() queue?

Posted on 2004-04-20
11
401 Views
Last Modified: 2010-04-01
Hi, I have a server right now that sends text to my client very fast, and the problem is, is that the client gets text, but not all of it, and often mangled so that there are duplicates of what is sent once. I am thinking that this is a problem with that when the server sends the text, the client is not recieving it fast enough and it only gets half of it or something. However, I have read up on it, and I have seen that when a message it sent from a Sock to a Sock, and the listening socket is not currently using recv(), then it just waits until it does, and the information being sent just "stacks" up. Any help? Thanks.
Matthew

Snippet of Source
SERVER
Init of Socket and listen/accept ing
       int RetVal;
        SOCKET Sock;
        SOCKADDR_IN SockAddr;
        Sock = socket(AF_INET, SOCK_STREAM, 0);
        if(Sock == INVALID_SOCKET)
        {
           //MessageBox(NULL, "Invalid Socket", "ERROR", MB_OK);
           return;
        }
        SockAddr.sin_port = htons(listen_port);
        SockAddr.sin_family = AF_INET;
        SockAddr.sin_addr.s_addr = INADDR_ANY;
        if(bind(Sock, (SOCKADDR *)(&SockAddr), sizeof(SockAddr)) == SOCKET_ERROR)
        {
            //MessageBox(NULL, "SocketBind", "ERROR", MB_OK);
            PostQuitMessage(1);
        }
        //setsockopt(Sock, SOL_SOCKET, SO_REUSEADDR, 1, sizeof(int))
        listen(Sock, 10);
        SOCKET TempSock = SOCKET_ERROR;
        while(TempSock == SOCKET_ERROR && con != 1)
        {
            TempSock = accept(Sock, NULL, NULL);
        }
Then it goes on to send info like this...
send(Sock, "hello there", 12, 0);
send(Sock, "\nMy name is Matthew", 20, 0);
send(Sock, "\nI like pie...", 15, 0);
send(Sock, "\nPlease give me cheese and I will thank you", 44, 0);



CLIENT
As Global Vars
SOCKET Sock;
SOCKADDR_IN SockAddr;

       SockAddr.sin_port = htons(7777);
       SockAddr.sin_family = AF_INET;
       SockAddr.sin_addr.s_addr = INADDR_ANY;
       if(bind(Sock, (SOCKADDR *)(&SockAddr), sizeof(SockAddr)) == SOCKET_ERROR)
       {
                cout << "Attempt to bind failed! Try a different Port..." << endl;
       }
       listen(Sock, 1);
       cout << "Listening..." << endl;
       cout << endl;
       SOCKET TempSock = SOCKET_ERROR;
       //SOCKADDR_IN sckadr;
       while(TempSock == SOCKET_ERROR)
       {
           TempSock = accept(Sock, NULL, NULL);
       }
       Sock = TempSock;
       cout << "\a\a\a\aIncoming Connection Accepted..." << endl;

Then it starts recieving messages in a separate thread while "cin" ing for messages to send to server (which also listens for messages in this same way)...
int RetVal;
char mesg[256];
while(TRUE)
{
        RetVal = recv(Sock, (char*)mesg, 256, 0);
        if((RetVal == 0) || (RetVal == WSAECONNRESET))
        {
            closesocket(Sock);
            cout << "Connection Terminated...";
            char tm[15];
            SYSTEMTIME st;
            GetLocalTime(&st);
            if(GetTimeFormat(LOCALE_SYSTEM_DEFAULT, LOCALE_NOUSEROVERRIDE, &st, NULL, tm, 15))
               cout << "(" << tm << ")";
            cout << endl;
               return;
        }
        else if(RetVal != SOCKET_ERROR)
        {
            cout << mesg;
        }
        else if(RetVal == SOCKET_ERROR)
        {
            cout << "Connection Terminated...";
            char tm[15];
            SYSTEMTIME st;
            GetLocalTime(&st);
            if(GetTimeFormat(LOCALE_SYSTEM_DEFAULT, LOCALE_NOUSEROVERRIDE, &st, NULL, tm, 15))
                  cout << "(" << tm << ")" << endl;
            cout << endl;
            closesocket(Sock);
            return;
        }
}
return;
0
Comment
Question by:BlakIXE
  • 5
  • 3
  • 3
11 Comments
 
LVL 39

Assisted Solution

by:itsmeandnobodyelse
itsmeandnobodyelse earned 62 total points
ID: 10870998
The client must not call bind(), listen() and accept() but connect() to the server's IP and port.

A successful connect() of the client will occur if  the server has a successful accept().

Tell me, if you need more info.

Regards, Alex


0
 

Author Comment

by:BlakIXE
ID: 10874946
Yea, sorry about the misinformment thing.
  Both Client and Server listen and connect. Wierd eh?
  But it works to connect an all.
  The problem is the garbled and jumbled text.

BlakIXE
0
 
LVL 39

Expert Comment

by:itsmeandnobodyelse
ID: 10875550
1. You should post the connect() code also ...

2. I can see more than one send(..) but only one recv(). After that the connection is closed
    throwing away any further message(s)...

Regards, Alex
0
Master Your Team's Linux and Cloud Stack

Come see why top tech companies like Mailchimp and Media Temple use Linux Academy to build their employee training programs.

 
LVL 39

Expert Comment

by:itsmeandnobodyelse
ID: 10875589
>> The problem is the garbled and jumbled text.

You have a 256 byte buffer that you fill with using that while(TRUE) loop. But you don't save the text read somewhere but the next recv() overwrites the contents previously read.

    RetVal = recv(Sock, (char*)mesg, 256, 0);          // second read overwrites first read

So you should do something like this:

   char msg[4096];  // Make a big buffer
   int received = 0;

   while(TRUE)
   {
           RetVal = recv(Sock, &msg[received], 4096 - received, 0);
           if (RetVal > 0)
           {
                received += RetVal;
           }
           else if (...
           {
           }        
   }

Regards, Alex

       
0
 
LVL 8

Accepted Solution

by:
mxjijo earned 63 total points
ID: 10891209

itsmeandnobodyelse,
    I guess BlakIXE's method also would work, because it looks like he is printing whatever he receives
before he calls the next recv. So even if there are 1000 bytes in the the TCP buffer, he can very well recv
blocks of 256 and display it without a problem.

    I guess BlakIXE's problem is even simpler, you have to put a '\0' at the end of all received buffer before you print it out. If you dont have \0 then out cout will print the whole buffer until it fins a \0.

Try this
       else if(RetVal != SOCKET_ERROR)
        {
            mesg [RetVal] = 0;            // <--------------- add this line.
            cout << mesg;
        }

~j
0
 
LVL 39

Expert Comment

by:itsmeandnobodyelse
ID: 10891752
mxjijo,

you are right: there is a  'printing' on cout after reading successfully. Maybe it should be written to a file also, as cout's from a thread may get improperly outputted.

if the socket is non-blocking the socket most likely returns with SOCKET_ERROR and WSAEWOULDBLOCK. If not it waits til the socket is disconnected by the client or is broken. A RetVal of  0 only is returned if the client gracefully terminated the connection using a shutdown() and a sufficient wait time before closesocket(). A RetVal of WSAECONNRESET never is returned as all WSA errors only could received only by calling WSAGetLastError() after a returned RetVal of SOCKET_ERROR.

A terminating zero to the char buffer received must be added only if the send messages cut the zero character. However, the send statements posted above all include a zero character.

Regards, Alex
0
 
LVL 8

Expert Comment

by:mxjijo
ID: 10891957

hey..... hold on ...

are you using non-blocking sockets ?? where do you handle  WSAEWOULDBLOCK ??

Also I think in the above messages where you have a \n in front you need to send one more character
to get to th \0 at the end. Did I count them correct ?

Use
sendto (socket, "whatever", strlen ("whatever") + 1, 0);

0
 

Author Comment

by:BlakIXE
ID: 10900555
Well, I added one extra length thing for the text I was sending, and that worked to stop it adding text to the end of messages....However, text is still not getting through. I will try sending it to a file first to see if cout is the problem, but I don't think it is.
I have a "dir" command, that gets the files in the current directory, and when I test it on my computer, (both client and server on same computer) it works great!, however, when I try to use the server on a different machine over a network, the directory command fizzles and screws with the text, so the problem is still there. I will do the file thing and check back with you guys, thanks a bunch.

BlakIXE
0
 

Author Comment

by:BlakIXE
ID: 10900560
oh yea, no, I am not using non-blocking
0
 
LVL 39

Expert Comment

by:itsmeandnobodyelse
ID: 10900883
Did you call WSAGetLastError() to get the specific socket error different from SOCKET_ERROR == -1 ?

What OS has the remote server? Same as your's? Or do you have a Little-Endian / Big-Endian connection?

Regards, Alex
0
 
LVL 8

Expert Comment

by:mxjijo
ID: 10903873

Okay.. now I guess whatever you receive is not getting mangled. - good.
Now to the other missing text problem.
There are a few methods to isolate the problem.

1) Check out the error code and make sure the number of bytes sent is correct.

2) Use a sniffer (Ethreal or MS network monitor) and see what happens to the packet / dest IP/ port number etc)
   You may use TDIMon.exe from sysinternals as well.

Still if you use UDP there is no guarentee that the packet will make it over to the other end.
Use UDP only if it is absolutely necessary (line streaming / broadcasting etc)
0

Featured Post

Windows Server 2016: All you need to know

Learn about Hyper-V features that increase functionality and usability of Microsoft Windows Server 2016. Also, throughout this eBook, you’ll find some basic PowerShell examples that will help you leverage the scripts in your environments!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Introduction This article is the first in a series of articles about the C/C++ Visual Studio Express debugger.  It provides a quick start guide in using the debugger. Part 2 focuses on additional topics in breakpoints.  Lastly, Part 3 focuses on th…
Container Orchestration platforms empower organizations to scale their apps at an exceptional rate. This is the reason numerous innovation-driven companies are moving apps to an appropriated datacenter wide platform that empowers them to scale at a …
The goal of the video will be to teach the user the concept of local variables and scope. An example of a locally defined variable will be given as well as an explanation of what scope is in C++. The local variable and concept of scope will be relat…
The viewer will learn how to clear a vector as well as how to detect empty vectors in C++.

803 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question