Solved

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

Posted on 2004-04-20
11
394 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
Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

 
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

Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

Question has a verified solution.

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

Suggested Solutions

Title # Comments Views Activity
c++ mixing int and strings in multi array 8 71
Interoperability issue between VC++ (ocx) & VB.NET applications 7 73
Problem with SqlConnection 4 159
What is sub-make ? 2 38
Article by: SunnyDark
This article's goal is to present you with an easy to use XML wrapper for C++ and also present some interesting techniques that you might use with MS C++. The reason I built this class is to ease the pain of using XML files with C++, since there is…
Written by John Humphreys C++ Threading and the POSIX Library This article will cover the basic information that you need to know in order to make use of the POSIX threading library available for C and C++ on UNIX and most Linux systems.   [s…
The viewer will learn how to use the return statement in functions in C++. The video will also teach the user how to pass data to a function and have the function return data back for further processing.
The viewer will learn how to clear a vector as well as how to detect empty vectors in C++.

914 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

15 Experts available now in Live!

Get 1:1 Help Now