socket transmission

C

cerr

hi There,

I have a piece of code in C and wanted to write a little simulator for
it in Perl. I basically wanna be listening on port 16001 and on
reception i wanna send back an acknowledgement "POK\0". I thought I
got this accomplished but for some reason my client doesn't seem to
understand the acknowledge string.
What I got in perl:
while (1){
my $client = $prssock->accept();
print "Got client\n";
while(<$client>) {
print "$_\n";
$prgstr.=$_;
print $client "POK";
print "POK\n";
}
print "lost client!\n";
}
and in C:
rc = write(_prg->prg_bus.bus_sock, response, strlen(response)); //
where response = "POK\0"

I'm not sure what I'm doing wrong here... :( Any suggestions? Would it
be because of the null character? I don't think so, eh?
The client side just checks if "POK" exists in the received
string...and for some reason it can't see the one coming back from my
perl script.... that puzzles me..

Thanks,
 
J

Jens Thoms Toerring

cerr said:
I have a piece of code in C and wanted to write a little simulator for
it in Perl. I basically wanna be listening on port 16001 and on
reception i wanna send back an acknowledgement "POK\0". I thought I
got this accomplished but for some reason my client doesn't seem to
understand the acknowledge string.
What I got in perl:
while (1){
my $client = $prssock->accept();
print "Got client\n";
while(<$client>) {
print "$_\n";
$prgstr.=$_;
print $client "POK";
print "POK\n";
}
print "lost client!\n";
}
and in C:
rc = write(_prg->prg_bus.bus_sock, response, strlen(response)); //
where response = "POK\0"

That means that you just send the three letters 'P', 'O' and 'K'.
I'm not sure what I'm doing wrong here... :( Any suggestions? Would it
be because of the null character? I don't think so, eh?
The client side just checks if "POK" exists in the received
string...and for some reason it can't see the one coming back from my
perl script.... that puzzles me..

Well, you're definitely not sending a '\0' character over to
the client. But if that's no problem (since the client doesn't
expect it - but then, how does the client figure out that it
got to the end of a message? Or does it expect exactly three
characters?) there's still the issue with buffering. My guess
is that the data never get send over to the client since you
got buffered I/O per default. You could do e.g.

$old_handle = select $client;
$| = 1;
select $old_handle;

or perhaps just

$client->autoflush();

(depending on what you're using) to switch buffering off (it's
the same in C - I/O is (line- or fully) buffered by default and
this must be switched off if not wanted, using e.g. setvbuf() -
you may have to do that also in the C client). And if you decide
you want to send the '\0' character anyway try

print $client "POK\000";

On reading from the client I also see a problem with sending
just the three letters 'P', 'O' and 'K' to your server. Why
should the input operation '<$client>' stop waiting for more
data after that? It only stops when it either finds a '\n' or
the socket gets closed by the other side. If you want to ac-
cept three character long messages you would need to use e.g.
read() or sysread() and tell it explicitely about how many
chars you want.

I would recommend that you change your approach and instead
have the messages passed between client and server being ter-
minated with a '\n' character, otherwise I guess you will need
to do quite a bit more to get it to work.

Regards, Jens
 
C

C.DeRykus

And if you decide
you want to send the '\0' character anyway try

print $client "POK\000";

Hm, although not the OP's C client, a Perl
one would've picked it up:

server: print $socket "POK\0\n";

client: printf "%s %d %d\n", substr($ack,0,3),
ord(substr $ack,3,1),ord(substr $ack,4,1);

--> POK 0 10
 
C

C.DeRykus

Hm, although not the OP's C client, a Perl
one would've picked it up:

server: print $socket "POK\0\n";

client: printf "%s %d %d\n", substr($ack,0,3),
        ord(substr $ack,3,1),ord(substr $ack,4,1);

   --> POK 0 10

No, I see that I added "\n" which changes the
scenario.
 
P

Peter J. Holzer

That means that you just send the three letters 'P', 'O' and 'K'.


Well, you're definitely not sending a '\0' character over to
the client. But if that's no problem (since the client doesn't
expect it - but then, how does the client figure out that it
got to the end of a message? Or does it expect exactly three
characters?) there's still the issue with buffering. My guess
is that the data never get send over to the client since you
got buffered I/O per default. You could do e.g.

$old_handle = select $client;
$| = 1;
select $old_handle;

Unless cerr is using a very old perl, this shouldn't be a problem:

perldoc IO::Socket says:

| NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE
|
| As of VERSION 1.18 all IO::Socket objects have autoflush turned on
| by default. This was not the case with earlier releases.
|
| NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE

[...]
On reading from the client I also see a problem with sending
just the three letters 'P', 'O' and 'K' to your server. Why
should the input operation '<$client>' stop waiting for more
data after that? It only stops when it either finds a '\n' or
the socket gets closed by the other side. If you want to ac-
cept three character long messages you would need to use e.g.
read() or sysread() and tell it explicitely about how many
chars you want.

You could also set $/ = \3; or set $/ = "\0" and modify the C code to
send the terminating \0 as well:

rc = write(_prg->prg_bus.bus_sock, response, strlen(response)+1); //

I suspect that the latter is intended since the OP keeps mentioning
"POK\0" in the text although both his programs only send "POK".

I would recommend that you change your approach and instead
have the messages passed between client and server being ter-
minated with a '\n' character, otherwise I guess you will need
to do quite a bit more to get it to work.

Not that much more.

However, using "\n" (or "\r\n") as a line terminator has one big
advantage: You can test your server with telnet.

hp
 
J

Jens Thoms Toerring

Unless cerr is using a very old perl, this shouldn't be a problem:
perldoc IO::Socket says:
| NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE
| As of VERSION 1.18 all IO::Socket objects have autoflush turned
| on by default. This was not the case with earlier releases.

Ah, I didn't have a look at this for obviosuly a long time (but
there remains the question if cerr is using IO::Socket).
You could also set $/ = \3; or set $/ = "\0" and modify the C code to
send the terminating \0 as well:

Thanks, I wasn't aware that this can be done that easily, nice
to be made aware of that!
Best regards, Jens
 
P

Peter J. Holzer

[...several problems...]
[...]
Unless cerr is using a very old perl, this shouldn't be a problem:
perldoc IO::Socket says:
| NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE
| As of VERSION 1.18 all IO::Socket objects have autoflush turned
| on by default. This was not the case with earlier releases.

Ah, I didn't have a look at this for obviosuly a long time (but
there remains the question if cerr is using IO::Socket).

True, but since he calls $prssock->accept() I think it is quite likely
that $prssock is an IO::Socket.

hp
 
J

Jens Thoms Toerring

True, but since he calls $prssock->accept() I think it is quite likely
that $prssock is an IO::Socket.

Yes, that makes a lot of sense.
Best regards. Jens
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
474,215
Messages
2,571,113
Members
47,711
Latest member
RosalindKe

Latest Threads

Top