Solved

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

Posted on 2004-04-20
11
389 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
 
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
Highfive + Dolby Voice = No More Audio Complaints!

Poor audio quality is one of the top reasons people don’t use video conferencing. Get the crispest, clearest audio powered by Dolby Voice in every meeting. Highfive and Dolby Voice deliver the best video conferencing and audio experience for every meeting and every room.

 
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

IT, Stop Being Called Into Every Meeting

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

Join & Write a Comment

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…
This article will show you some of the more useful Standard Template Library (STL) algorithms through the use of working examples.  You will learn about how these algorithms fit into the STL architecture, how they work with STL containers, and why t…
The goal of the tutorial is to teach the user how to use functions in C++. The video will cover how to define functions, how to call functions and how to create functions prototypes. Microsoft Visual C++ 2010 Express will be used as a text editor an…
The viewer will learn how to user default arguments when defining functions. This method of defining functions will be contrasted with the non-default-argument of defining functions.

708 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

Need Help in Real-Time?

Connect with top rated Experts

13 Experts available now in Live!

Get 1:1 Help Now