Sean, IMHO, you are correct to be unhappy. In fairness, not only is half of the code "on the client" - half of it IS the client :) It's just that the example is not very practical; no data are sent for the client to read. The vast majority of (good) sockets programming is handling errors and non-responsive peers.
The most consistent story I have gotten is that ConnectionQueue is the preferred way to create a server; last I looked, it was broken, at least in Pharo. It also offers no way, out of the box, to specify on which interface the server should be listening - that's kind of important. Sadly, it polls for connections rather than blocking (just one Process, of course) until an event is generated as a client tries to connect. It screams for some serious cleanup. I have yet to look at what happens when, whether by socket or socket stream (which was not in the stream hierarchy and hence missing important protocol), the other side is non-responsive. I doubt it will be ideal, which is to block only the Process attempting the connection. Ditto that for DNS activity; only the process attempting it should suffer if the server is slow or completely unresponsive. IMHO, sockets should not have timeouts; they should simply block only the thread that initiates activity so that everything else moves along as expected. On a server, a separate process can look for inactivity and terminate offending connections; on a client, either a similar watchdog or the user can make the call as to when to give up. An event/announcement should be triggered off of a socket when its peer closes to enable timely cleanup. Testing some of this stuff requires establishing lengthy I/O and powering off hubs at strategic times. Until a system can survive that without hanging more than a calling thread, it's not ready. Bill testLocalServerAndClientNoThread "11-09 - try a server and a client in the same image. Try without the separate read thread." | server port client serverSocket serverSocketStream text read | port := 4900. "11-09 - gag the prompter below" serverSocket := nil. server := ConnectionQueue portNumber:port queueLength:5. [ client := SocketStream openConnectionToHostNamed:'localhost' port:port. [ serverSocket isNil ] whileTrue:[ serverSocket := server getConnectionOrNil. ]. serverSocketStream := SocketStream on:serverSocket. text := 'Long live Tux!'. serverSocketStream nextPutAll:text; flush. read := client nextMany:text size. self should:[ read = text ]. Transcript nextPutAll:'Just to make the point, we read: '; nextPutAll:read; cr; flush. ] ensure:[ server destroy. serverSocketStream close. client close. ]. "11-09 - no prompts" serverSocket := serverSocket. client := client. serverSocketStream := serverSocketStream. " NetworkSmokeTestCase prod:#testLocalServerAndClientNoThread. " ________________________________________ From: pharo-project-boun...@lists.gforge.inria.fr [pharo-project-boun...@lists.gforge.inria.fr] On Behalf Of Sean P. DeNigris [s...@clipperadams.com] Sent: Sunday, August 29, 2010 5:05 PM To: pharo-project@lists.gforge.inria.fr Subject: [Pharo-project] Sockets in Pharo CollaborActive Book The description of sockets at http://book.pharo-project.org/book/networking/Socket/ is: Socket is one of the main networking classes. You can create a new TCP socket with the message #newTCP. > > This example creates a TCP socket and puts it into listening mode. After a > client has connected, it reads data from the socket. > > | server client | > server := Socket newTCP. > server listenOn: 12345 backlogSize: 4. > server waitForConnectionFor: 600. > client := server accept. > client receiveData > Huh?! It looks like half the code in this snippet belongs on the server, and the other half on the client. I tried: Server doit: server := Socket newTCP. server listenOn: 12345 backlogSize: 4. server waitForConnectionFor: 600. Client doit: server := Socket newTCP. server listenOn: 12345 backlogSize: 4. server waitForConnectionFor: 600. client := server accept. client receiveData. but the server just hung forever. After flopping around for a while, and checking the swiki, it seemed to be listenOn:backlogSize: that was the problem. Everything went well with: Server DoIt: server := Socket newTCP. server listenOn: 8080. server waitForConnectionFor: 600. server sendData: 'Hello from the server' Client PrintIt: client := Socket newTCP. client connectTo: (NetNameResolver localHostAddress) port: 8080. client receiveData. Anyway, I'd like to have this be clearer, but my knowledge is very basic. Also, the class comment for socket reads "...Sockets are the lowest level of networking object in Squeak and are not normally used directly..." so is this where we want to direct people first? Thanks. Sean -- View this message in context: http://forum.world.st/Sockets-in-Pharo-CollaborActive-Book-tp2399361p2399361.html Sent from the Pharo Smalltalk mailing list archive at Nabble.com. _______________________________________________ Pharo-project mailing list Pharo-project@lists.gforge.inria.fr http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project _______________________________________________ Pharo-project mailing list Pharo-project@lists.gforge.inria.fr http://lists.gforge.inria.fr/cgi-bin/mailman/listinfo/pharo-project