473,573 Members | 3,036 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

strange problem with send() and recv()

Tom
I try to write a simple tcp based job queue server. It's purpose is to
get commands from a client and store them in a queue (STL). The server
has a thread which checks periodically the queue, executes the commands
in it and removes them from the queue after done so. It also has a
thread for every client connection. I am using the low level SOCKET
API. My server is a Win32 console app and my client is MFC. The
followinf struct is passed through the sockets:
typedef struct
{
int iCmdId;
char szJobID[JOBIDLENGTH];
char szWorkPath[PATHLENGTH];
char szUser[USERLENGTH];
} SERVERCMD;

The client can query the server about the jobs currently queued. The
server sends then each item (the whole struct) in the queue to the
client. The wired problem with this function is that for a while
everything seems fine. I get all queued jobs listed in my clients
CListBox. But after repeatingly calling the ListJobs() function my data
get somehow corrupted (although the queue doesn't change). In the
following I post the sourcode for the server's and client's ListJobs()
function and the debuging output which clearly shows the problem.

server:
void ListJobs( SOCKET client )
{
int bytesSent = 0;
char buffer[5];
itoa( CmdQueue.size() , buffer, 10 );

bytesSent = send( client, (char*)&buffer, sizeof(buffer), 0 );
LogMessage( "ListJobs: sent %d bytes -> nJobs=%d\n", bytesSent,
CmdQueue.size() );

for (int i=0; i<CmdQueue.size (); i++)
{
SERVERCMD job = CmdQueue[i];
bytesSent = send( client, (char*)&job, sizeof(SERVERCM D), 0 );
LogMessage( "ListJobs: sent %d bytes of jobdata\n", bytesSent
);
}
LogMessage( "\n" );
}

client:
SERVERCMD * ListJobs( int * nJobs )
{
if ( sockClient == NULL )
return NULL;

int bytesSent,bytes Recv;
SERVERCMD * jobs;

// send list request to server
SERVERCMD job;
job.iCmdId = CMD_LSTJOB;
bytesSent = send( sockClient, (char*)&job, sizeof(SERVERCM D), 0 );
if ( bytesSent == SOCKET_ERROR )
return NULL;

// receive number of jobs
*nJobs = 0;
char buffer[5];
bytesRecv = recv( sockClient, (char*)&buffer, sizeof(buffer), 0 );

if ( bytesRecv != SOCKET_ERROR )
{
*nJobs = atoi( buffer );
debug("ListJobs : reveiced %d bytes -> nJobs=%d\n", bytesRecv,
*nJobs);

// allocate space for jobs
size_t jobsSize = *nJobs * sizeof(SERVERCM D);
jobs = (SERVERCMD*)mal loc( jobsSize );
debug("ListJobs : allocating %d bytes\n", jobsSize);

// receive jobs
for (int i=0;i<*nJobs; i++)
{
bytesRecv = recv( sockClient, (char*)&(jobs[i]),
sizeof(SERVERCM D), 0 );
if ( bytesRecv == SOCKET_ERROR ) return NULL;
debug("ListJobs : received %d bytes of jobdata\n",
bytesRecv);
}
debug("\n");
}
else
return NULL;

return jobs;
}

In the following debugging output 2 jobs were put into the queue. The
queue was then queried multible times.

server:
ListJobs: sent 5 bytes -> nJobs=1 <-- one job in queue
ListJobs: sent 1228 bytes of jobdata

ListJobs: sent 5 bytes -> nJobs=2 <-- two jobs in queue
ListJobs: sent 1228 bytes of jobdata
ListJobs: sent 1228 bytes of jobdata

ListJobs: sent 5 bytes -> nJobs=2 <-- two jobs in queue
ListJobs: sent 1228 bytes of jobdata
ListJobs: sent 1228 bytes of jobdata
(...)
ListJobs: sent 5 bytes -> nJobs=2
ListJobs: sent 1228 bytes of jobdata
ListJobs: sent 1228 bytes of jobdata

client:
ListJobs: reveiced 5 bytes -> nJobs=1 <-- one job in queue
ListJobs: allocating 1228 bytes <-- size of 1*SERVERCMD
ListJobs: received 1228 bytes of jobdata <-- this is OK

ListJobs: reveiced 5 bytes -> nJobs=2 <-- two jobs in queue
ListJobs: allocating 2456 bytes <-- OK
ListJobs: received 1228 bytes of jobdata <-- OK
ListJobs: received 1228 bytes of jobdata <-- OK

(after quering queue multible times)

ListJobs: reveiced 5 bytes -> nJobs=2
ListJobs: allocating 2456 bytes
ListJobs: received 1228 bytes of jobdata
ListJobs: received 232 bytes of jobdata <-- Woho, what's that?

ListJobs: reveiced 5 bytes -> nJobs=0 <-- HELP!!!
ListJobs: allocating 0 bytes

I really need help with that. Maybe this is a thread thing, but in my
test I used only one client.

__

Tom

Nov 15 '05 #1
6 3243
Tom
I forgot to mention that this effect only appears when I run the server
on a different host. When both, server and client, are on one host the
problem do not occure.

Nov 15 '05 #2
On Mon, 8 Aug 2005, Tom wrote:
I try to write a simple tcp based job queue server. It's purpose is to
get commands from a client and store them in a queue (STL). The server
has a thread which checks periodically the queue, executes the commands
in it and removes them from the queue after done so. It also has a
thread for every client connection. I am using the low level SOCKET
API. My server is a Win32 console app and my client is MFC. The
followinf struct is passed through the sockets:
typedef struct
{
int iCmdId;
char szJobID[JOBIDLENGTH];
char szWorkPath[PATHLENGTH];
char szUser[USERLENGTH];
} SERVERCMD;

The client can query the server about the jobs currently queued. The
server sends then each item (the whole struct) in the queue to the
client. The wired problem with this function is that for a while
everything seems fine. I get all queued jobs listed in my clients
CListBox. But after repeatingly calling the ListJobs() function my data
get somehow corrupted (although the queue doesn't change). In the
following I post the sourcode for the server's and client's ListJobs()
function and the debuging output which clearly shows the problem.

server:
void ListJobs( SOCKET client )
{
int bytesSent = 0;
char buffer[5];
itoa( CmdQueue.size() , buffer, 10 );

bytesSent = send( client, (char*)&buffer, sizeof(buffer), 0 );
LogMessage( "ListJobs: sent %d bytes -> nJobs=%d\n", bytesSent,
CmdQueue.size() );

for (int i=0; i<CmdQueue.size (); i++)
{
SERVERCMD job = CmdQueue[i];
bytesSent = send( client, (char*)&job, sizeof(SERVERCM D), 0 );
LogMessage( "ListJobs: sent %d bytes of jobdata\n", bytesSent
);
}
LogMessage( "\n" );
}

client:
SERVERCMD * ListJobs( int * nJobs )
{
if ( sockClient == NULL )
return NULL;

int bytesSent,bytes Recv;
SERVERCMD * jobs;

// send list request to server
SERVERCMD job;
job.iCmdId = CMD_LSTJOB;
bytesSent = send( sockClient, (char*)&job, sizeof(SERVERCM D), 0 );
if ( bytesSent == SOCKET_ERROR )
return NULL;

// receive number of jobs
*nJobs = 0;
char buffer[5];
bytesRecv = recv( sockClient, (char*)&buffer, sizeof(buffer), 0 );

if ( bytesRecv != SOCKET_ERROR )
{
*nJobs = atoi( buffer );
debug("ListJobs : reveiced %d bytes -> nJobs=%d\n", bytesRecv,
*nJobs);

// allocate space for jobs
size_t jobsSize = *nJobs * sizeof(SERVERCM D);
jobs = (SERVERCMD*)mal loc( jobsSize );
debug("ListJobs : allocating %d bytes\n", jobsSize);

// receive jobs
for (int i=0;i<*nJobs; i++)
{
bytesRecv = recv( sockClient, (char*)&(jobs[i]),
sizeof(SERVERCM D), 0 );
if ( bytesRecv == SOCKET_ERROR ) return NULL;
debug("ListJobs : received %d bytes of jobdata\n",
bytesRecv);
}
debug("\n");
}
else
return NULL;

return jobs;
}

In the following debugging output 2 jobs were put into the queue. The
queue was then queried multible times.

server:
ListJobs: sent 5 bytes -> nJobs=1 <-- one job in queue
ListJobs: sent 1228 bytes of jobdata

ListJobs: sent 5 bytes -> nJobs=2 <-- two jobs in queue
ListJobs: sent 1228 bytes of jobdata
ListJobs: sent 1228 bytes of jobdata

ListJobs: sent 5 bytes -> nJobs=2 <-- two jobs in queue
ListJobs: sent 1228 bytes of jobdata
ListJobs: sent 1228 bytes of jobdata
(...)
ListJobs: sent 5 bytes -> nJobs=2
ListJobs: sent 1228 bytes of jobdata
ListJobs: sent 1228 bytes of jobdata

client:
ListJobs: reveiced 5 bytes -> nJobs=1 <-- one job in queue
ListJobs: allocating 1228 bytes <-- size of 1*SERVERCMD
ListJobs: received 1228 bytes of jobdata <-- this is OK

ListJobs: reveiced 5 bytes -> nJobs=2 <-- two jobs in queue
ListJobs: allocating 2456 bytes <-- OK
ListJobs: received 1228 bytes of jobdata <-- OK
ListJobs: received 1228 bytes of jobdata <-- OK

(after quering queue multible times)

ListJobs: reveiced 5 bytes -> nJobs=2
ListJobs: allocating 2456 bytes
ListJobs: received 1228 bytes of jobdata
ListJobs: received 232 bytes of jobdata <-- Woho, what's that?

ListJobs: reveiced 5 bytes -> nJobs=0 <-- HELP!!!
ListJobs: allocating 0 bytes

I really need help with that. Maybe this is a thread thing, but in my
test I used only one client.

__

Tom


.... And the remaining of your post :
I forgot to mention that this effect only appears when I run the server
on a different host. When both, server and client, are on one host the
problem do not occure.


comp.lang.c isn't the right newsgroup to post to for your problem. I've a
feeling that c.u.p. might be more appropriate.

X-post & f.u.2 where relevant

--
"Je deteste les ordinateurs : ils font toujours ce que je dis, jamais ce
que je veux !"
"The obvious mathematical breakthrough would be development of an easy
way to factor large prime numbers." (Bill Gates, The Road Ahead)
Nov 15 '05 #3

Tom wrote:
I forgot to mention that this effect only appears when I run the server
on a different host. When both, server and client, are on one host the
problem do not occure.


Hi,

Your code looks rather like C++ to me... But your problems are likely
to do
with send/recv, which aren't really on topic in comp.lang.c++ either.
I suggest you ask in comp.os.ms-windows.program mer.win32, you will
get better help there (or in comp.unix.progr ammer, assuming your
problems aren't windows specific).

<OT> Look at recv documention for your system,
you may not get as many bytes as you ask for,
in which case you need to try again until you do. recv
takes flags that modify this behavior, look at them. <OT>

-David

Nov 15 '05 #4
Tom
I apologize for posting my issue on this group. I already posted it to
comp.os.ms-windows.program mer.win32,
microsoft.publi c.win32.program mer.networks and alt.winsock.pro gramming.
But I tought maybe I can get help here too.

Nov 15 '05 #5
On 8 Aug 2005 09:03:31 -0700, "Tom" <ba***@b3s.de > wrote:
I try to write a simple tcp based job queue server. It's purpose is to
get commands from a client and store them in a queue (STL). The server
As others have noted the STL part is C++ and offtopic in c.l.C, but
this is relatively small and easily ignorable. "Mixed" declarations
(that is, not solely at the beginning of a block) and double-slash
comments which were introduced in C++ _are_ standard in C as of C99,
but not yet universally implemented. And double-slash comments are
still unwise in news postings, since those may get line breaks (wraps)
added at various points, and this breaks // comments but does not harm
/* */ comments. (It also harms long preprocessor #directives, the only
other place lines are significant.)
has a thread which checks periodically the queue, executes the commands
in it and removes them from the queue after done so. It also has a
thread for every client connection. I am using the low level SOCKET
Server thread per connection/client scales poorly; see any week (of
the last N years) of comp.programmin g.threads. But leave that for now.
API. My server is a Win32 console app and my client is MFC. The
followinf struct is passed through the sockets:
typedef struct
{
int iCmdId;
char szJobID[JOBIDLENGTH];
char szWorkPath[PATHLENGTH];
char szUser[USERLENGTH];
} SERVERCMD;
In general it's a poor idea to send C-language structs over a network;
compilers on different types of systems can lay them out differently,
and sometimes also different compilers or the same compiler with
different options on the same system type. This is why you see proper
network protocols specified in terms of actual bits (or nowadays
usually octets) on the wire and not in C or other HLL. But since you
apparently are using Wintel and probably the same compiler at both
(all) endpoints, and structs that are _mostly_ chars, leave that also.
The client can query the server about the jobs currently queued. The
server sends then each item (the whole struct) in the queue to the
client. The wired problem with this function is that for a while
everything seems fine. I get all queued jobs listed in my clients
CListBox. But after repeatingly calling the ListJobs() function my data
get somehow corrupted (although the queue doesn't change). In the
following I post the sourcode for the server's and client's ListJobs()
function and the debuging output which clearly shows the problem.

server:
void ListJobs( SOCKET client )
{
int bytesSent = 0;
char buffer[5];
itoa( CmdQueue.size() , buffer, 10 );
itoa() is not standard in C or C++. sprintf() is. If the number of
jobs is > 9999 this overflows the buffer, formally causing Undefined
Behavior although in practice on nearly all if not all machines this
particular UB doesn't actually cause harm until you get to at least 6
digits and probably 8 digits. And the latter at least probably won't
happen because you'll hit other limits first. (Like uptime!)
bytesSent = send( client, (char*)&buffer, sizeof(buffer), 0 );
LogMessage( "ListJobs: sent %d bytes -> nJobs=%d\n", bytesSent,
CmdQueue.size() );

for (int i=0; i<CmdQueue.size (); i++)
{
SERVERCMD job = CmdQueue[i];
bytesSent = send( client, (char*)&job, sizeof(SERVERCM D), 0 );
Perhaps clearer to use sizeof(job), and for an object/expression (but
not a typename) can omit the parentheses = sizeof job .
LogMessage( "ListJobs: sent %d bytes of jobdata\n", bytesSent
);
}
LogMessage( "\n" );
}

client:
SERVERCMD * ListJobs( int * nJobs )
{
if ( sockClient == NULL )
return NULL;

int bytesSent,bytes Recv;
SERVERCMD * jobs;

// send list request to server
SERVERCMD job;
job.iCmdId = CMD_LSTJOB;
bytesSent = send( sockClient, (char*)&job, sizeof(SERVERCM D), 0 );
if ( bytesSent == SOCKET_ERROR )
return NULL;

// receive number of jobs
*nJobs = 0;
char buffer[5];
bytesRecv = recv( sockClient, (char*)&buffer, sizeof(buffer), 0 );

if ( bytesRecv != SOCKET_ERROR )
{
*nJobs = atoi( buffer );
debug("ListJobs : reveiced %d bytes -> nJobs=%d\n", bytesRecv,
*nJobs);
If the server numjobs was > 9999 this reads an unterminated (and
possibly very wrong) value on which atoi() isn't safe. In fact atoi()
isn't safe in the presence of almost any error; strtol (and ul, and ll
and ull on C99 systems) handles some errors but not unterminated.
// allocate space for jobs
size_t jobsSize = *nJobs * sizeof(SERVERCM D);
jobs = (SERVERCMD*)mal loc( jobsSize );
The cast wouldn't be needed in C, but is in C++, and you don't check
the result is nonnull before using it (below). In C++ it is briefer,
clearer, and more robust to just write jobs = new SERVERCMD [*nJobs],
which also throws (by default) on allocation failure.
debug("ListJobs : allocating %d bytes\n", jobsSize);
%d expects an int (signed) but jobsSize is size_t which is definitely
unsigned and may be a different size than int or unsigned int. In C99
there is a specific modifier for this; in C90 and C++ probably best to
cast to and specify unsigned long, or perhaps unsigned long long if
you have it. Or in C++ use << instead, to a stringstream if necessary.
// receive jobs
for (int i=0;i<*nJobs; i++)
{
bytesRecv = recv( sockClient, (char*)&(jobs[i]),
sizeof(SERVERCM D), 0 );
if ( bytesRecv == SOCKET_ERROR ) return NULL;
debug("ListJobs : received %d bytes of jobdata\n",
bytesRecv);
}
debug("\n");
}
else
return NULL;

return jobs;
}

In the following debugging output 2 jobs were put into the queue. The
queue was then queried multible times.

As already noted, recv() on a bytestream protocol like TCP can receive
only part of what you asked for (and was sent). You need to use
MSG_COMP if available, which I don't think it is on (most?) Winsock,
or be prepared to read multiple pieces and combine them.

- David.Thompson1 at worldnet.att.ne t
Nov 15 '05 #6
Dave Thompson <da************ *@worldnet.att. net> writes:
[...]
As others have noted the STL part is C++ and offtopic in c.l.C, but
this is relatively small and easily ignorable. "Mixed" declarations
(that is, not solely at the beginning of a block) and double-slash
comments which were introduced in C++ _are_ standard in C as of C99,
but not yet universally implemented. And double-slash comments are
still unwise in news postings, since those may get line breaks (wraps)
added at various points, and this breaks // comments but does not harm
/* */ comments. (It also harms long preprocessor #directives, the only
other place lines are significant.)
Lines are also significant in string literals. E.g., "splitting this
across lines" will cause problems.

[...]
In general it's a poor idea to send C-language structs over a network;
compilers on different types of systems can lay them out differently,
and sometimes also different compilers or the same compiler with
different options on the same system type. This is why you see proper
network protocols specified in terms of actual bits (or nowadays
usually octets) on the wire and not in C or other HLL. But since you
apparently are using Wintel and probably the same compiler at both
(all) endpoints, and structs that are _mostly_ chars, leave that also.


It's not uncommon for structs to be laid out in the same way for
different compilers on the same platform, so there's some hope of
combining code compiled with different compilers, but generally it's
not wise to depend on it.

--
Keith Thompson (The_Other_Keit h) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Nov 15 '05 #7

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

4
3359
by: Jane Austine | last post by:
Running Python 2.3 on Win XP It seems like socket is working interdependently with subprocesses of the process which created socket. ------------------------------------ #the server side >>> import socket >>> s=socket.socket(socket.AF_INET,socket.SOCK_STREAM) >>> s.bind(('localhost',9000))
1
1851
by: Sori Schwimmer | last post by:
Hi, I am working on an application which involves interprocess communication. More to the point, processes should be able to notify other processes about certain situations, so the "notifyees" would be able to act in certain ways. As processes are distributed on several machines, in different physical locations, my thinking was:
8
1999
by: Skink | last post by:
Hi, I'm preparing a python server that sends java classes and resources to custom java class loader. In order to make it faster I don't want to use URLClassLoader that uses HTTP protocol 1.0 and for each class/resource creates own connection. Instead I'd like to use raw sockets with simple protocol: - class loader sends a line terminated...
17
6107
by: SW1 | last post by:
I wrote a small program which does something like tftp - transfering files and some chat, anyway i got a problem with fwrite, here is a snippet of my code: while(length > 0) { putchar('.'); //These were for error checking if(length <= bsize) { //Buffer is bigger than remaining File realloc(buffer,length * sizeof(char)); //resize buffer to...
2
2171
by: Matt | last post by:
I wrote the tcp socket client-server program that the server will echo the message received from the client. In client program: char sendBuf; while(1) { cout << "Enter message:"; cin.getline(sendBuf,100); rVal = send(theSocket, sendBuf, strlen(sendBuf), 0);
5
11666
by: Terry | last post by:
It's my understanding of UDP sockets that if there is a thread blocked on a "recvFrom()" call and other thread sends a UDP packet to some address, that if the machine on the other end isn't up, that the "recvFrom()" call should just continue blocking. Right? What I'm seeing is that when I send a packet to a particular address that is not...
0
1418
by: Tony Caduto | last post by:
Hi, I am developing a socket server in C# and I want it to be blocking. Anyway I have it working with threads, as each client connects the socket spawned from the accept method is sent to a client thread. In each thread I have a loop like below: the data_available method is a wrapper around Socket.Poll() so I can use it in miliseconds...
4
1425
by: Tomas Machala | last post by:
Hi, I'm trying to make an application communicating over TCP/IP. It should do only one thing - write received data to console and terminate itself when "exit" received. Problem is that if I send some string to this application, it'll receive that string and many unwanted "new line" characters on its end. Examle: If I send "some_string" ...
1
2000
by: ifmusic | last post by:
I have This Code. Token.c: typedef struct { unsigned char orden; char ciudad; unsigned char ip; //que son del router Asociado a la ciudad unsigned int puerto; // """ //int socket; }Ciudad;
0
7701
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it. First, let's disable language...
0
8029
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. ...
0
8204
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that...
0
8068
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the...
0
6424
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then...
0
3734
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in...
0
3735
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
1
2222
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system
1
1307
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.