What follows is a program that sends a char[array] to a server and then is "supposed" to receive back a response.
I'm using stdio fwrite/fread calls after associating a socket to a stream using fdopen.
The program successfully sends the array but then hangs on the fread call.... Any ideas? I put the signal handler in with the "IN DO LOOP" line so I could see if it was handling, but it only prints out IN DO LOOP once and locks up.
if (foo_in[3] == 95)
printf(" Initialization Sequence Received OK \n\n");
for (number=48; number < (bytes+48); number++) {
printf("%c",foo_in[number]);
}
*/
printf("\n\n");
return 0;
}
Super Bakemono
09-07-2001, 04:16 AM
It pro'ly locks up cause there is nothing to read. I haven't done much with sockets so I can't help you more than that...
The Kooman
09-07-2001, 05:10 AM
Originally posted by lizard3x:
Hi Lizard,
A few observations, comments, suggestions and questions ...
<STRONG>The program successfully sends the array but then hangs on the fread call.... Any ideas? I put the signal handler in with the "IN DO LOOP" line so I could see if it was handling, but it only prints out IN DO LOOP once and locks up.</STRONG>
Where is the server? If you echo the line at the server line, does it show up?
Aren't you actually writing sizeof(foo) elements, each of size 1 byte, instead of 1 element which is sizeof(foo) bytes long? Also be careful of taking care of byte endianness - convert to network... esp. if you're sending a multibyte data (which is what you're doing here - one huge multibyte data).
You are using line buffered i/o. Are you sure your data has gone out? Is it still there in the buffer? Try a fflush() to ensure its gone out. Check whats going on at the server end - if the server is
actually receiving the data.
<STRONG>
do {
printf("IN DO LOOP\n");
clearerr(rx);
numin = fread(foo_in,sizeof(foo_in),1,rx);
</STRONG>
Put a printf() here and see what happens?
I've just skimmed through the code without an in-depth look - perhaps you'll find the answers yourself when you look at the suggestions. My biggest suggestion is to forget stream i/o and stick to
read write (while keeping in mind network endian issues).
HTH (at least a bit)!
[ 07 September 2001: Message edited by: The Kooman ]
pinoy
09-07-2001, 06:08 AM
It's likely fread is stuck waiting for more data to come in. Is the other end sending sizeof(foo)?
Just use read/write, don't bother with stdio's buffering.
TheLinuxDuck
09-07-2001, 11:48 AM
lizard3x:
How about someone else's opinion?? (^=
Here are some comments, not sure if they relate to the problem, but could be:
char *ServIP; /* server IP address */
...
ServIP = "##.##.##.##"; /* gateway address */
The code isn't actually allocating any memory here, it's only providing a pointer to some memory that has not yet been allocated. This will more than likely cause an overrun, and possibly a core dump. Try either:
or if the IP will never change, and you don't mind it being a static string, then try
char *ServIP="##.##.##.##";
numout = fwrite(foo,sizeof(foo),1,tx);
The code has stored how many characters were written into numout, but what if the write fails? Here, how can the socket expect to read anything if there's nothing written? In this case, the value in numout should be 1. So, I would test it against 1 before attemping to read.
That will guarantee that something was written before the read is called.
As for the main read loop, I would prolly put a printf right before and right after the fread.
Other than that, I think I would agree with LloydM about using read/write instead of fread/fwrite, although they are easier to implement (IMHO).
Hope this helps!
lizard3x
09-07-2001, 12:13 PM
Thanks everyone for the suggestions.
I'm sorry I included the whole darn program. The problem is definitely with the fread() call. I have an exact duplicate of this program using simple read()/write()s, and as you've all suggested-it works fine.
I wanted to implement the same code using the stdio streams for a variety of reasons-first and foremost, because Stevens (Unix Network Programming) and Gay (Linux Socket Programming) says so! Something about "overhead" and such! :-) But in addition to that, to simply learn another method.
I know my program is talking to the server as I can watch the TCP transactions on Ethereal (awesome program)-but no data transmission occurs. Perhaps it's a fflush(ing) issue.
I just wanted to hear some suggestions, and perhaps this info sheds a slight bit more light on it.
The code isn't actually allocating any memory here, it's only providing a pointer to some memory that has not yet been allocated. This will more than likely cause an overrun, and possibly a core dump. Try either:
Nothing wrong with that. It is the same as:
char *ServIP = "###.###.###.###";
All it's doing is simply setting ServIP to the address of the literal string "###.###.###.###". It shouldn't cause a segfault.
The problem with FILE* io is that, they're buffered. The problem could be at the server side, or at the client side.
e.g. if the server hasn't issued a fflush then it's likely the data is still sitting at userspace and not being passed to the TCP stack. Or, the client may block if it hasn't received all requested bytes to read from the TCP stack. That's why I suggested raw read()/write(). This is only affected by the nagle algorithm (a short timeout, that tries to buffer writes).
TheLinuxDuck
09-07-2001, 05:40 PM
Well, if that doesn't dip my face in hot tar!
I have always been taught to allocate the memory before assigning anything to a pointer.
I guess we learn something new every day.
pinoy
09-07-2001, 06:26 PM
Yes, you should *initialize* pointers before you use it. If you're copying data into the area pointed to by your pointer, then it should be pointing to valid area where it can hold enough of that data. Remember, a pointer can point to anything, including static text.
:)
Stuka
09-09-2001, 02:21 AM
Hey, Lloyd...is that little trick you wrote up possible because of compiler activity? As in, the compiler is putting the static text into the <asm mode> data section, rather than someplace dynamic? </asm mode> Because on the face of it, that would seem like dangerous coding practice. Mind you, I'm more of a C++ fan, and would handle it w/a string, but I am curious... ;)
pinoy
09-09-2001, 05:58 AM
Stuka, literal strings are always stored somewhere in memory. I can't remember the layout exactly, but I think it is usually just before the static data, and they are *static* (ie they remain for the program's entire life). It may even be with the static data. Remember the cpu's registers can only hold numbers or pointers in the case of a string.
eg.
char *str = "Test";
The compiler might put the string "Test" in 0xf00df00d. Which means that the pointer str contains 0xf00df00d.
char *str = NULL;
str = "Test";
Again if "Test" was stored in 0xf00df00d, str will initially contain 0 (or NULL).
str = "Test", basically sets str to the address of "Test" or 0xf00df00d in this case. So as you can see the first example is practically identical to the second one.
Another note to remember, the compiler will usually optimize space, if for example the same literal string appears more than once, the compiler will only store one version.
e.g.
char *str = "Hello";
char *p = NULL;
p = "Hello";
p is probably equal to str. I say probably because I can't verify this without access to gcc currently.
justlinux.com
Copyright Internet.com Inc. All Rights Reserved.