Link to home
Start Free TrialLog in
Avatar of BlakIXE
BlakIXE

asked on

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

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;
SOLUTION
Avatar of itsmeandnobodyelse
itsmeandnobodyelse
Flag of Germany image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of BlakIXE
BlakIXE

ASKER

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
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
>> 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

       
ASKER CERTIFIED SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
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

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);

Avatar of BlakIXE

ASKER

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
Avatar of BlakIXE

ASKER

oh yea, no, I am not using non-blocking
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

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)