[Pharo-project] receiving tcp messages
Hi, I would need to listen to a TCP/IP port and receive plain text. What is the way to do that in Pharo these days? Cheers, Doru -- www.tudorgirba.com "Every thing has its own flow"
Doru, On 24 Feb 2012, at 10:14, Tudor Girba wrote:
Hi,
I would need to listen to a TCP/IP port and receive plain text. What is the way to do that in Pharo these days?
Cheers, Doru
-- www.tudorgirba.com
"Every thing has its own flow"
Have a look at the ZnServer hierarchy, specifically ZnSingleThreadedServer which does not spawn threads for each incoming request (not used as such in Zn, but easier to understand) and ZnMultiThreadedServer which does spawn threads for each incoming request (the current default in Zn). Start with #listenLoop. The code is slightly more complicated that example code because of all the error handling, but I am sure you will be able to read it. HTH, Sven -- Sven Van Caekenberghe http://stfx.eu Smalltalk is the Red Pill
Thanks, Sven. Will do. Cheers, Doru On Fri, Feb 24, 2012 at 10:37 AM, Sven Van Caekenberghe <sven@beta9.be> wrote:
Doru,
On 24 Feb 2012, at 10:14, Tudor Girba wrote:
Hi,
I would need to listen to a TCP/IP port and receive plain text. What is the way to do that in Pharo these days?
Cheers, Doru
-- www.tudorgirba.com
"Every thing has its own flow"
Have a look at the ZnServer hierarchy, specifically ZnSingleThreadedServer which does not spawn threads for each incoming request (not used as such in Zn, but easier to understand) and ZnMultiThreadedServer which does spawn threads for each incoming request (the current default in Zn). Start with #listenLoop. The code is slightly more complicated that example code because of all the error handling, but I am sure you will be able to read it.
HTH,
Sven
-- Sven Van Caekenberghe http://stfx.eu Smalltalk is the Red Pill
-- www.tudorgirba.com "Every thing has its own flow"
Hi, I advanced a bit, but I am still in trouble. I just want to get a communication going with a simple telnet app. Here is what I did: In Pharo: ZnMultiThreadedServer startDefaultOn: 1701. ZnMultiThreadedServer default delegate: PXSLogDelegate new. ZnMultiThreadedServer default log addListener: ZnTranscriptLogger new.. In the Windows 7 command line: - telnet localhost 1701 - then press ENTER And in the Transcript I get: 2012-02-24 13:16:57 201678 D Executing request/response loop 2012-02-24 13:17:02 201678 D ZnUnknownHttpMethod while reading request 2012-02-24 13:17:02 201678 D Closing stream The problem is that I do not want to get as high as http. Is there a way to get this working, or is Zinc too high level for this task? I forgot to mention that I am a total newbie in this area :) Cheers, Doru On Fri, Feb 24, 2012 at 10:56 AM, Tudor Girba <tudor@tudorgirba.com> wrote:
Thanks, Sven. Will do.
Cheers, Doru
On Fri, Feb 24, 2012 at 10:37 AM, Sven Van Caekenberghe <sven@beta9.be> wrote:
Doru,
On 24 Feb 2012, at 10:14, Tudor Girba wrote:
Hi,
I would need to listen to a TCP/IP port and receive plain text. What is the way to do that in Pharo these days?
Cheers, Doru
-- www.tudorgirba.com
"Every thing has its own flow"
Have a look at the ZnServer hierarchy, specifically ZnSingleThreadedServer which does not spawn threads for each incoming request (not used as such in Zn, but easier to understand) and ZnMultiThreadedServer which does spawn threads for each incoming request (the current default in Zn). Start with #listenLoop. The code is slightly more complicated that example code because of all the error handling, but I am sure you will be able to read it.
HTH,
Sven
-- Sven Van Caekenberghe http://stfx.eu Smalltalk is the Red Pill
-- www.tudorgirba.com
"Every thing has its own flow"
-- www.tudorgirba.com "Every thing has its own flow"
Doru, I meant: look at ZnServer and friends for inspiration, not to solve the problem of how to write a simple TCP server. If you do just: ZnServer startDefaultOn: 1701 and then talk HTTP over telnet, it will work as expected: $ telnet 127.0.0.1 1701 Trying 127.0.0.1... Connected to localhost. Escape character is '^]'. GET / HTTP/1.1 HTTP/1.1 200 OK Content-Type: text/html;charset=utf-8 Content-Length: 1195 Date: Fri, 24 Feb 2012 12:51:03 GMT Server: Zinc HTTP Components 1.0 <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html> <head> <title>Zinc HTTP Components</title> <style type="text/css"> body { color: black; â¦. Writing your own delegate means handling HTTP requests and answering with HTTP responses. (Zn contains a lot of these). But I am not sure that you should do that for your problem, on one hand it might be overkill, on the other hand, HTTP _is_ one of the easiest protocols, not need to invent something new. If you use HTTP, you get all you need with Zn. The question is: what is on the other side ? what is the client ? Sven On 24 Feb 2012, at 13:20, Tudor Girba wrote:
Hi,
I advanced a bit, but I am still in trouble.
I just want to get a communication going with a simple telnet app. Here is what I did:
In Pharo: ZnMultiThreadedServer startDefaultOn: 1701. ZnMultiThreadedServer default delegate: PXSLogDelegate new. ZnMultiThreadedServer default log addListener: ZnTranscriptLogger new..
In the Windows 7 command line: - telnet localhost 1701 - then press ENTER
And in the Transcript I get: 2012-02-24 13:16:57 201678 D Executing request/response loop 2012-02-24 13:17:02 201678 D ZnUnknownHttpMethod while reading request 2012-02-24 13:17:02 201678 D Closing stream
The problem is that I do not want to get as high as http. Is there a way to get this working, or is Zinc too high level for this task?
I forgot to mention that I am a total newbie in this area :)
Cheers, Doru
On Fri, Feb 24, 2012 at 10:56 AM, Tudor Girba <tudor@tudorgirba.com> wrote:
Thanks, Sven. Will do.
Cheers, Doru
On Fri, Feb 24, 2012 at 10:37 AM, Sven Van Caekenberghe <sven@beta9.be> wrote:
Doru,
On 24 Feb 2012, at 10:14, Tudor Girba wrote:
Hi,
I would need to listen to a TCP/IP port and receive plain text. What is the way to do that in Pharo these days?
Cheers, Doru
-- www.tudorgirba.com
"Every thing has its own flow"
Have a look at the ZnServer hierarchy, specifically ZnSingleThreadedServer which does not spawn threads for each incoming request (not used as such in Zn, but easier to understand) and ZnMultiThreadedServer which does spawn threads for each incoming request (the current default in Zn). Start with #listenLoop. The code is slightly more complicated that example code because of all the error handling, but I am sure you will be able to read it.
HTH,
Sven
-- Sven Van Caekenberghe http://stfx.eu Smalltalk is the Red Pill
-- www.tudorgirba.com
"Every thing has its own flow"
-- www.tudorgirba.com
"Every thing has its own flow"
Hi Sven, Thanks, but I did not explain my problem correctly. My problem is actually super trivial. I have a server that throws continuously plain text (actually, it's a logging facility), and I need to implement a client that connects to it and consumes the plain text endlessly without any feedback to the server. So, essentially, there is no communication protocol involved. Cheers, Doru On Fri, Feb 24, 2012 at 2:02 PM, Sven Van Caekenberghe <sven@beta9.be> wrote:
Doru,
I meant: look at ZnServer and friends for inspiration, not to solve the problem of how to write a simple TCP server.
If you do just: ZnServer startDefaultOn: 1701 and then talk HTTP over telnet, it will work as expected:
$ telnet 127.0.0.1 1701 Trying 127.0.0.1... Connected to localhost. Escape character is '^]'. GET / HTTP/1.1
HTTP/1.1 200 OK Content-Type: text/html;charset=utf-8 Content-Length: 1195 Date: Fri, 24 Feb 2012 12:51:03 GMT Server: Zinc HTTP Components 1.0
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html> <head> <title>Zinc HTTP Components</title> <style type="text/css"> body {  color: black; â¦.
Writing your own delegate means handling HTTP requests and answering with HTTP responses. (Zn contains a lot of these).
But I am not sure that you should do that for your problem, on one hand it might be overkill, on the other hand, HTTP _is_ one of the easiest protocols, not need to invent something new. If you use HTTP, you get all you need with Zn.
The question is: what is on the other side ? what is the client ?
Sven
On 24 Feb 2012, at 13:20, Tudor Girba wrote:
Hi,
I advanced a bit, but I am still in trouble.
I just want to get a communication going with a simple telnet app. Here is what I did:
In Pharo: ZnMultiThreadedServer startDefaultOn: 1701. ZnMultiThreadedServer default    delegate: PXSLogDelegate new. ZnMultiThreadedServer default    log addListener: ZnTranscriptLogger new..
In the Windows 7 command line: - telnet localhost 1701 - then press ENTER
And in the Transcript I get: 2012-02-24 13:16:57 201678 D Executing request/response loop 2012-02-24 13:17:02 201678 D ZnUnknownHttpMethod while reading request 2012-02-24 13:17:02 201678 D Closing stream
The problem is that I do not want to get as high as http. Is there a way to get this working, or is Zinc too high level for this task?
I forgot to mention that I am a total newbie in this area :)
Cheers, Doru
On Fri, Feb 24, 2012 at 10:56 AM, Tudor Girba <tudor@tudorgirba.com> wrote:
Thanks, Sven. Will do.
Cheers, Doru
On Fri, Feb 24, 2012 at 10:37 AM, Sven Van Caekenberghe <sven@beta9.be> wrote:
Doru,
On 24 Feb 2012, at 10:14, Tudor Girba wrote:
Hi,
I would need to listen to a TCP/IP port and receive plain text. What is the way to do that in Pharo these days?
Cheers, Doru
-- www.tudorgirba.com
"Every thing has its own flow"
Have a look at the ZnServer hierarchy, specifically ZnSingleThreadedServer which does not spawn threads for each incoming request (not used as such in Zn, but easier to understand) and ZnMultiThreadedServer which does spawn threads for each incoming request (the current default in Zn). Start with #listenLoop. The code is slightly more complicated that example code because of all the error handling, but I am sure you will be able to read it.
HTH,
Sven
-- Sven Van Caekenberghe http://stfx.eu Smalltalk is the Red Pill
-- www.tudorgirba.com
"Every thing has its own flow"
-- www.tudorgirba.com
"Every thing has its own flow"
-- www.tudorgirba.com "Every thing has its own flow"
On 24 Feb 2012, at 14:28, Tudor Girba wrote:
Thanks, but I did not explain my problem correctly. My problem is actually super trivial. I have a server that throws continuously plain text (actually, it's a logging facility), and I need to implement a client that connects to it and consumes the plain text endlessly without any feedback to the server. So, essentially, there is no communication protocol involved.
OK, but it is still not 100% clear: who is the client and who is the server ? A web server (Apache, Seaside, ZnServer) is a long running program that accepts connections from clients (web browsers, curl, ZnClient), interprets the requests and sends responses as replies; the initiaitive lies with the client. Such a server might generate a logging stream which is usually written to a file, but it could send the logging records to a logging server (like syslogd) that collects and/or processes them. Then the server becomes a client to the logging server, the initiative for the communication lies with the server-as-logging-client. The reverse also exists: you could connect to a server (Twitter) and ask for a specific data stream to be send to you. Then the server is like a notification/messaging/queueing system (some multithreading magic will be needed). The connection initiative lies with the client, but the data stream transfer is done on the server's initiative. Sven
On 02/24/2012 02:28 PM, Tudor Girba wrote:
Hi Sven,
Thanks, but I did not explain my problem correctly. My problem is actually super trivial. I have a server that throws continuously plain text (actually, it's a logging facility), and I need to implement a client that connects to it and consumes the plain text endlessly without any feedback to the server. So, essentially, there is no communication protocol involved.
Just use SocketStream. Since you are building a client it is trivial: stream := SocketStream openConnectionToHostNamed: host port: port. [stream isConnected] whileTrue: [ line := stream nextLineLf] ...or something like that (just see protocol of SocketStream). No need to use Socket directly - I tend to keep repeating that on mailinglists. :) For a trivial *forking server* you can load Blackfoot from SS and "copy" from it, it is a stripped down server basically. regards, Göran
On 24 Feb 2012, at 15:42, Göran Krampe wrote:
On 02/24/2012 02:28 PM, Tudor Girba wrote:
Hi Sven,
Thanks, but I did not explain my problem correctly. My problem is actually super trivial. I have a server that throws continuously plain text (actually, it's a logging facility), and I need to implement a client that connects to it and consumes the plain text endlessly without any feedback to the server. So, essentially, there is no communication protocol involved.
Just use SocketStream. Since you are building a client it is trivial:
stream := SocketStream openConnectionToHostNamed: host port: port. [stream isConnected] whileTrue: [ line := stream nextLineLf]
...or something like that (just see protocol of SocketStream). No need to use Socket directly - I tend to keep repeating that on mailinglists. :)
For a trivial *forking server* you can load Blackfoot from SS and "copy" from it, it is a stripped down server basically.
regards, Göran
He wants a server, I think. Here is an example of a very simple forking server, without error handling code: | serverSocket serverProcess | serverSocket := Socket newTCP. serverSocket listenOn: 8888 backlogSize: 5. serverProcess := [ [ | clientSocket stream line | clientSocket := serverSocket waitForAcceptFor: 900. stream := SocketStream on: clientSocket. [ [ (line := stream nextLine) ~= 'quit' ] whileTrue: [ Transcript crLog: line. stream nextPutAll: line reverse; crlf; flush ]. stream close ] fork. ] repeat ] fork. { serverProcess. serverSocket }. And here is how it works: $ telnet 127.0.0.1 8888 Trying 127.0.0.1... Connected to localhost. Escape character is '^]'. hello olleh doru urod smalltalk klatllams quit Connection closed by foreign host. Make sure to inspect the code above, so that you can #terminate the server process and #close the server socket. The process browser is useful too (don't forget to update it), as will be Socket allInstances and/or Socket allInstances do: #close (Warning: you will crash/hang your image until you get this 100% right with proper error handling.) HTH, Sven -- Sven Van Caekenberghe http://stfx.eu Smalltalk is the Red Pill
Hi Sven (and Goran), Thanks a lot! This is pretty much what I was looking for. I will poke around some more. Cheers, Doru On 24 Feb 2012, at 16:14, Sven Van Caekenberghe wrote:
On 24 Feb 2012, at 15:42, Göran Krampe wrote:
On 02/24/2012 02:28 PM, Tudor Girba wrote:
Hi Sven,
Thanks, but I did not explain my problem correctly. My problem is actually super trivial. I have a server that throws continuously plain text (actually, it's a logging facility), and I need to implement a client that connects to it and consumes the plain text endlessly without any feedback to the server. So, essentially, there is no communication protocol involved.
Just use SocketStream. Since you are building a client it is trivial:
stream := SocketStream openConnectionToHostNamed: host port: port. [stream isConnected] whileTrue: [ line := stream nextLineLf]
...or something like that (just see protocol of SocketStream). No need to use Socket directly - I tend to keep repeating that on mailinglists. :)
For a trivial *forking server* you can load Blackfoot from SS and "copy" from it, it is a stripped down server basically.
regards, Göran
He wants a server, I think.
Here is an example of a very simple forking server, without error handling code:
| serverSocket serverProcess | serverSocket := Socket newTCP. serverSocket listenOn: 8888 backlogSize: 5. serverProcess := [ [ | clientSocket stream line | clientSocket := serverSocket waitForAcceptFor: 900. stream := SocketStream on: clientSocket. [ [ (line := stream nextLine) ~= 'quit' ] whileTrue: [ Transcript crLog: line. stream nextPutAll: line reverse; crlf; flush ]. stream close ] fork. ] repeat ] fork. { serverProcess. serverSocket }.
And here is how it works:
$ telnet 127.0.0.1 8888 Trying 127.0.0.1... Connected to localhost. Escape character is '^]'. hello olleh doru urod smalltalk klatllams quit Connection closed by foreign host.
Make sure to inspect the code above, so that you can #terminate the server process and #close the server socket. The process browser is useful too (don't forget to update it), as will be
Socket allInstances
and/or
Socket allInstances do: #close
(Warning: you will crash/hang your image until you get this 100% right with proper error handling.)
HTH,
Sven
-- Sven Van Caekenberghe http://stfx.eu Smalltalk is the Red Pill
-- www.tudorgirba.com "Problem solving efficiency grows with the abstractness level of problem understanding."
On 02/24/2012 06:38 PM, Tudor Girba wrote:
Hi Sven (and Goran),
Thanks a lot! This is pretty much what I was looking for.
As I wrote - if you are after a forking *server* - then load Blackfoot from SS and use it as a base. I took Kom and stripped it down to its barest form and made a base class etc, it should be obvious. It does basically what Sven wrote. regards, Göran
for telnet-kind-of communication, i think there is already base classes for doing that.. i have no image before my eyes now, but look for things related to mail client, and ftp.. the base class is called something like CommandBlahBlah, which implements a simple "readline" over socket. 2012/2/24 Göran Krampe <goran@krampe.se>:
On 02/24/2012 06:38 PM, Tudor Girba wrote:
Hi Sven (and Goran),
Thanks a lot! This is pretty much what I was looking for.
As I wrote - if you are after a forking *server* - then load Blackfoot from SS and use it as a base. I took Kom and stripped it down to its barest form and made a base class etc, it should be obvious. It does basically what Sven wrote.
regards, Göran
-- Best regards, Igor Stasenko.
participants (4)
-
Göran Krampe -
Igor Stasenko -
Sven Van Caekenberghe -
Tudor Girba