Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Listening to IP ports

0 views
Skip to first unread message

Pat

unread,
Dec 29, 2001, 5:00:06 AM12/29/01
to
Hello,

I want to set up an application which recieves data on a TCP port (2001).
Are there sample scripts for that, because I can't seem to get it working
with the man pages..

Pat.


Cameron Laird

unread,
Dec 29, 2001, 9:26:26 AM12/29/01
to
In article <CugX7.36865$Xh5.2...@news.quicknet.nl>,
.
.
.
1. You can start with <URL: http://
starbase.neosoft.com/~claird/comp.lang.tcl/tcl-examples.html#socket >
2. I'll be back Monday to give a worked-out
example specific to your question.
3. Others will probably offer other example
Web pages; all of these are accessible
through the URL in 1.
--

Cameron Laird <Cam...@Lairds.com>
Business: http://www.Phaseit.net
Personal: http://starbase.neosoft.com/~claird/home.html

Neil Madden

unread,
Dec 29, 2001, 10:31:48 AM12/29/01
to
The following is the usual setup I use for such stuff. This example will
deal with multiple connections on the same socket. If you only want one
connection, then ignore the fileevent stuff and put the readData proc
directly into the accept proc in a while loop (while {[gets $sock line]
>= 0} ...)

# Open the server socket:
set sock [socket -server accept 2001]
# This proc is called each time a new connection is made:
proc accept {sock addr port} {
puts "Connection $sock from ${addr}:$port"
# Set up fileevents here to read data from the port, or
# just read directly.
fconfigure $sock -blocking 0
# uncomment the following for binary data:
#fconfigure $sock -translation binary -encoding binary
fileevent $sock readable [list readData $sock]
}

# This is called every time data is available on a connection:
proc readData {sock} {
# Read data from a socket when available
puts "Reading data from $sock"
if {[catch {gets $sock} line] || [eof $sock]} {
puts "socket closed"
catch {close $sock}
# I'm not sure if this bit is needed, but better
# on the safe side:
if {[string length $line]} {
puts "Last bit of data: $line"
}
} else {
puts "Read $line from $sock"
}
}

vwait forever; # only needed in tclsh

Pat

unread,
Jan 4, 2002, 4:44:25 AM1/4/02
to

"Neil Madden" <nem...@cs.nott.ac.uk> wrote in message
news:3C2DE1E4...@cs.nott.ac.uk...

> The following is the usual setup I use for such stuff. This example will
> deal with multiple connections on the same socket. If you only want one
> connection, then ignore the fileevent stuff and put the readData proc
> directly into the accept proc in a while loop (while {[gets $sock line]
> >= 0} ...)
>
Thanks for the code. It all looks understandable, but when I execute it, I
get the error that the channel was not open for reading. I am using TCL
under windows (win2K), will that matter???

Regards, Pat.

Bruce Hartweg

unread,
Jan 4, 2002, 6:07:36 AM1/4/02
to

"Pat" <zijnadresbeni...@NOSPAMhetwasietsmet.nl> wrote in message news:3c3579a3$0$225$4d4e...@read.news.nl.uu.net...
It shouldn't. Are you running what Neil gave directly ? or did you change it a little
to fit your code ? If so are you sure you are not trying to read from the original server socket?

Bruce

Pat

unread,
Jan 4, 2002, 6:27:58 AM1/4/02
to

"Bruce Hartweg" <brha...@bigfoot.com> wrote in message
news:_1gZ7.277$5Y4....@news.cpqcorp.net...

>
> "Pat" <zijnadresbeni...@NOSPAMhetwasietsmet.nl> wrote in message
news:3c3579a3$0$225$4d4e...@read.news.nl.uu.net...
> It shouldn't. Are you running what Neil gave directly ? or did you change
it a little
> to fit your code ? If so are you sure you are not trying to read from the
original server socket?
>
Not that I know...
I have the following:

proc Open_conn {} {
set sock [socket -server accept 20001]
.time.status.label2 configure -text "Connection $sock "


# Set up fileevents here to read data from the port, or
# just read directly.
fconfigure $sock -blocking 0
# uncomment the following for binary data:
#fconfigure $sock -translation binary -encoding binary
fileevent $sock readable [list readData $sock]
}

With the fileevent, wish calls an error..


Bruce Hartweg

unread,
Jan 4, 2002, 6:35:13 AM1/4/02
to

"Pat" <zijnadresbeni...@NOSPAMhetwasietsmet.nl> wrote in message news:3c3591e8$0$224$4d4e...@read.news.nl.uu.net...

Yep, you missed a step. You are trying to read from the server socket itself.

The socket returned from the [socket -server ...] command is ONLY for accepting connections
no I/O occurs on it. When a new connection is received, the specified proc (in this case accept)
is called with 3 arguments - the first one being a socket that is opened for I/O - this is the socket
you need to fconfigure and setup the fileevent on.

Bruce

Pat

unread,
Jan 4, 2002, 7:59:54 AM1/4/02
to

"Bruce Hartweg" <brha...@bigfoot.com> wrote in message
news:TrgZ7.278$5Y4....@news.cpqcorp.net...

>
> Yep, you missed a step. You are trying to read from the server socket
itself.
>
> The socket returned from the [socket -server ...] command is ONLY for
accepting connections
> no I/O occurs on it. When a new connection is received, the specified proc
(in this case accept)
> is called with 3 arguments - the first one being a socket that is opened
for I/O - this is the socket
> you need to fconfigure and setup the fileevent on.

OKe... but what do I have to change to do that?
I can't see the difference with the code Neil gave. Could you give me a hint
here.
(it is obvious that I have only used file i/o with tcl).

Thanx,
pat


Bruce Hartweg

unread,
Jan 4, 2002, 9:36:55 AM1/4/02
to

"Pat" <zijnadresbeni...@NOSPAMhetwasietsmet.nl> wrote in message news:3c35a774$0$225$4d4e...@read.news.nl.uu.net...

Look again at Neil's example: the sock returned from the [socket -server ..] command
is NEVER used. (You might want to save it off in case you want to close it to stop
accepting new connections, but other than that you don't really need it).

the key is that the first param to the socket command after the -server switch is a proc
name that is called each time a new connection is made (in Neil's example it was called
accept, but it can be any name you want) This proc is called with 3 args - the new socket
that was created for the connection, the address of the other end and the port on the other
end - it is inside this proc that the configuration of the socket is done - in your code you
never defined the accept proc - so when a new connection was attempted you would have
got an error about accept not being defined, but then you tried to configure your server socket
for I/O, which is a no-no.

On the server side the initial socket created is ONLY for accepting connections - not I/O.
Each new connection will automatically create a new socket for I/O and there can be multiple
of these open at the same time (up to some system limit of descriptors)

Once you get it, sockets in tcl are so simple (try any of this at the C level and it is unbelievable
how hard it is to do these simple things)

Bruce

Cameron Laird

unread,
Jan 4, 2002, 1:27:56 PM1/4/02
to
In article <e6jZ7.281$5Y4....@news.cpqcorp.net>,
Bruce Hartweg <brha...@bigfoot.com> wrote:
.
.
.

>Once you get it, sockets in tcl are so simple (try any of this at the C level and it is unbelievable
>how hard it is to do these simple things)
>
>Bruce
>
>
>

Network communication indeed is one of the glories of the
Tcl library.

Let's make this concrete. Here's what I regard as a canonical
example C-coded simple server example:
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <stdio.h>
#define LISTEN_LIMIT 20
#define SERVICE_PORT 3364
void simple_response(int );

int main(int argc, char **argv)
{
int listenfd, connfd;
pid_t childpid;
socklen_t clilen;
struct sockaddr_in cliaddr, servaddr;

listenfd = socket(AF_INET, SOCK_STREAM, 0);

bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
servaddr.sin_port = htons(SERVICE_PORT);

bind(listenfd, (struct sockaddr *) &servaddr, sizeof(servaddr));

listen(listenfd, LISTEN_LIMIT);

while (TRUE) {
clilen = sizeof(cliaddr);
connfd = accept(listenfd, (struct sockaddr *) &cliaddr, &clilen);
if ((childpid = fork()) == 0) {
close(listenfd);
simple_response(connfd);
exit(0);
}
close(connfd);
}
}


#define MAXLINE 80
/********
*
* In this example, echo the characters of the query back,
* reversed.
*
********/
void simple_response(int sockfd)
{
char line[MAXLINE], *ptr;
FILE *fpin, *fpout;

fpin = fdopen(sockfd, "r");
fpout = fdopen(sockfd, "w");

while (1) {
if (fgets(line, MAXLINE, fpin) == NULL)
return;
for (ptr = line + strlen(line) - 2; ptr >= line; ptr--)
putc(*ptr, fpout);
putc('\n', fpout);
fflush(fpout);
}
}
Judge for yourself how this compares to Tcl in readability
and maintainability.

One point that I think deserves emphasis, though, is Tcl's
remarkable portability. That simple little TCP/IP server
Bruce has been explaining works correctly under MacOS, OpenVMS,
Unix, and Win*. The C stuff above ... while, different C
libraries require select(), or poll(), or threading, in
place of fork() as a concurrency mechanism. Enjoy Tcl,
folks.

Pat

unread,
Jan 8, 2002, 3:57:16 AM1/8/02
to

"Bruce Hartweg" <brha...@bigfoot.com> wrote in message
news:e6jZ7.281$5Y4....@news.cpqcorp.net...

>
> Look again at Neil's example: the sock returned from the [socket -server
..] command
> is NEVER used. (You might want to save it off in case you want to close it
to stop
> accepting new connections, but other than that you don't really need it).

Wow!!! I finally got it working. Thanks a lot guys, for the help and for
your patience...

Pat.


0 new messages