socket - Open a TCP network connection : '''socket''' ?''options''? ''host port'' <
> '''socket -server''' ''command'' ?''options''? ''port'' This command opens a network socket and returns a channel identifier that may be used in future invocations of commands like read, puts and flush. At present only the [TCP] network protocol is supported; future releases may include support for additional protocols like [UDP] and [IPX]. The socket command may be used to open either the client or server side of a connection, depending on whether the '''-server''' switch is specified. See also the official documentation at http://www.purl.org/tcl/home/man/tcl8.5/TclCmd/socket.htm Server sockets can only accept incoming connections when Tcl has an event loop running. All sockets use the system [encoding] by default; this is probably not what you want, but it is up to the protocol to define or negotiate something more suitable. Something which is at first surprising is that the channel identifier returned by '''server -socket''' cannot be used to transfer any data (it can be [fconfigure]d and [close]d, but that's it). Tcl inherited this peculiarity from the underlying [C] APIs for sockets: the datatype for open connections (to other processes, machines, etc.) over which one transfers data was reused to keep track of server ports to which clients may connect, so it was easiest to handle both of them as Tcl channels. The channel that the server side may use to transfer data is the one which is passed to the ''command'' callback. ---- '''Service details''' Port numbers are integers but depending upon your system configuration you may be able to use symbolic names for some services. The calls the getservbyname sockets API function which uses a services database file to convert between port numbers and service names. ''This function is quite limited on certain platforms (eg:Windows)''. [slebetman]: this is partially untrue (see comment below). Some lists of protocols and their associated port numbers are: * Official [IANA] list [http://www.iana.org/assignments/port-numbers] (0.5+ MB text file). * http://www.akerman.ca/port-table.html * Network Sorcery list [http://www.networksorcery.com/enp/protocol/ip/ports00000.htm]. On unix-type systems you very likely have an /etc/services file which is used by this function. ''It typically has the same syntax as the official IANA list referenced above'' [slebetman]: this is also not true, similar syntax but not the same. The ''typical'' /etc/services file has the syntax: # comment service_name port_number/protocol alias where comments can appear at the end of line and aliases can be used instead of the service_name when requesting for the port number (for example both "smtp" and "mail" refer to port 25). The IANA list on the other hand has the syntax: service_name port_number/protocol description/comment # person who requested the port for the service OR relevant documentation In addition, for the IANA list, all text above the lines: Port Assignments: Keyword Decimal Description References ------- ------- ----------- ---------- are to be considered as comments. [slebetman]:On Windows, starting from Windows 2000 you have a C:\WINNT\SYSTEM32\DRIVERS\ETC\SERVICES or C:\WINDOWS\SYSTEM32\DRIVERS\ETC\SERVICES file serving the exact same function as the Unix counterpart and has exactly the same syntax. The currently shipping ''services'' file for Windows XP is dated 1999 so it doesn't have newer registered ports such as '''tcpmux''' and '''rje'''. Nonetheless this file is editable and can be easily updated by downloading the current 2006 IANA definitions from the net. [Stu] - 2007/02/16 : The [netinfo] extension provides easy access to the contents of /etc/services as well as /etc/protocols and /etc/hosts. ---- How to use the -async option? Pasted from the Tcl'ers chat dgp proc verify s { set msg [fconfigure $s -error] if {$msg ne ""} { # an error connecting } # set up to use $s } set s [socket -async $host $port] fileevent $s writable [list verify $s] dgp over the Tcl versions and platforms, I've found it helpful to test dgp [puts -nonewline $s ""] and [fconfigure $s -peername] to be *really* sure you have a successful socket connection. ---- [Cameron Laird] wrote in [the comp.lang.tcl newsgroup]: The most widely-used solution ''(for ensuring only a single instance of an app is running on one machine)'', I think, is to set up a do-nothing networking service. Have your application socket -server ... 5678 when it first starts. If it's unable to do so because another service is already on 5678, take that as a previous instance of the application. Otherwise, continue. For an implementation, see [How do I manage lock files in a cross platform manner in Tcl] Notice this approach is reasonably portable. CL himself notes, somewhat later, that this is a bit "tricky", and not on the main stream of socket use; it's really socket's contribution to the theme of [singleton application]s. ---- Sockets are also one way on [How can Tcl programs on two different machines communicate]. [JH] writes on sockets in http://aspn.activestate.com/ASPN/Cookbook/Tcl/Recipe/65436 . More possibilities are listed in the [Inventory of IPC methods]. Yet another example of socket service appears in http://moogy.unstable.org:8080/simple.sockets.tar.gz . http://www.tcl.tk/scripting/netserver.html is an excellent tutorial showing how to write both server and client sides of an echo service. ---- One little-known corner of TCP/IP is "[port 0 networking]". ---- Several challenges in effective network programming have to do with [DNS] pragmatics. [DKF] wrote, "numeric addresses are never resolved on socket creation on Unix, but they *are* on Windows (but I do not know if it is *really* doing it, as that depends on the Winsock implementation)." ---- One question that seems to arise often is about [how to send a file through a socket connection]. ---- As of 8.5, there's apparently no clean socket [introspection]. Socket handles '''do''' show up in "[file] channels sock*", though, so, as long as one is willing to rely on this slightly dirty match, the answer is computable. [DGP] See Tcl Feature Request 455867 [http://sourceforge.net/tracker/index.php?func=detail&aid=455867&group_id=10894&atid=360894]. ---- [GPS]: from the [Tcl Chatroom]: * [xmav000] i'm trying to implement a game client/server architecture. can anyone give me some hints which projects i could look at to get some more ideas. there probably are some chat client/server (which will have to be a part of course) * [GPS] xmav: I have some code for you. Server tclsh: % proc accept {s addr port} {puts $s "Hi and bye!"; close $s} % socket -server accept 8888 Client tclsh: % set s [socket localhost 8888] sock3 % gets $s Now the client will block, because the server isn't running its event loop. So go to the server tclsh and type: update and you will see in the client: Hi and bye! (Wikified soon) * [GPS] I'm not sure if that's enough of what you need. Everything for a game server should be built upon this foundation though. * [GPS] fileevent is the command you will use to process sockets when they are readable or writable. * [suchenwi] GPS: hey, that looks cool! PLEASE wikify it (plus discussion)! [GPS]: I would like to clarify a bit. [fileevent] interacts with the event loop allowing us to do other things (rather than just blocking) and have an event callback invoked when data is ready to be send/received on a [socket] channel. ---- [[ ... [ceptcl] ...]] ---- [kostix] '''Issues with remote disconnects and blocking sockets''' There's a problem of knowing that the remote wants to disconnect since there's no possibility to register a kind of callback for getting some info about changes in the socket's state. Here's what occur: 1. The remote wants to close the connection and sends a packet with the FIN flag set. 1. The local TCP/IP stack ACKnowledges this packet. 1. The remote transisions to the FIN-WAIT-2 state, and the local stack to the CLOSE-WAIT state. At this time, calls to '''gets''' will set the EOF state on the socket so that the subsequent calls to '''eof''' on it will return 1. 1. Since the Tcl script doesn't know that the remote initiated closng of the connection (unless it calls '''gets''' as described above), ''it can continue to send the data to the remote!'' Which the remote most probably doesn't want. The amount of data that can be sent depends on whether the remote wants to continue to receive the data from our endpoint, and which method of buffering is set for the socket. Most probably, the remote will send a packet with the RST flag set if it gets any not-yet-acknowledged packet from our endpoint w/o the FIN flag set. This will forcibly tear down the connection and any subsequent attempts to send the data to the remote will fail with EPIPE or ECONNRESET. The data to the remote may pour, however, until the local TCP/IP stack finally gets that RST packet. At least 2 data packets can be sent to the remote before we get this RST packet: one with the ACK on the initial FIN, and one that the remote will consider as bad (and will send its RST). So, from the standpoint of tracing the remote disconnects, the different buffering schemes should be used as described: * For big data streams (like files) '''full''' buffering or '''none''' buffering should be used. This will accomplish "all or nothing" approach: the file is either sent successfully or not. * For line-oriented ("interactive") protocols like SMTP line buffering should be used. Since each command to the remote is acknowledged by some other line of text from the remote, dicsonnects will be catched by the '''gets''' following '''puts'''. It would be cool to have some real means for getting the socket status, at least passive (through '''fconfigure''' or the like) but it seems current Tcl lacks this. In my Tcl 8.4.9 on Linux, '''fconfigure $sock -error''' doesn't indicate that half-closed connection state. May be it should do so. '''Update:''' at least on 8.5.2 under Linux '''fconfigure $sock -error''' seem to return "broken pipe" ''earlier'' than '''puts''' errors out. The error appears to be set after the first attempt to put data into unbuffered socket which was closed remotely. For some reason only the second attempt to send data to such socket will actually throw the "broken pipe" error. [JMN] 2006-10-17 related, and worse IMO.. there's apparently no way to trigger a half close on a Tcl Socket. It seems to me that Tcl is simply incapable of talking to certain TCP daemons such as spammassassin's spamc/spamd 1.0 protocol. This daemon relies on the client closing its '''write''' half of the channel to trigger the daemon to send a response. Tcl only lets you close the whole socket - so you never get the response. Just sending an EOF doesn't work. Quite a serious limitation of Tcl sockets.. no? [AMG]: Agreed. My suggestion is to create a command to unbundle a read/write channel into a pair of channels, one read-only and the other write-only. Then the halves can be separately closed. For symmetry, there could also be a command to bundle a read-only channel (e.g. stdin) and a write-only channel (e.g. stdout) into a read/write channel. This would make it possible to pass stdin/stdout to a procedure that accepts as an argument a single read/write channel (such as a socket). [Lars H], 2008-05-06: For splitting channels, there is [TIP]#301 [http://tip.tcl.tk/301]. There doesn't seem to be any implementation of that yet, however. [kostix], 2008-09-25: [TIP] #301 was rejected and superseded by new (pending) [TIP] #332 [http://tip.tcl.tk/332]. [ferrieux] 2008-09-26: not formally rejected, withdrawn ;-) To answer [JMN]'s concern about missing half-close for socket: good news, I think I will finish #332 pretty soon because there already is machinery at the C level for a generic notion of half-closes. They are even already implemented for pipes. So we just need to implement the half-close proc for sockets (with shutdown()) and expose the whole at Tcl level. For the impatient though, there is a workaround: on unix do [exec shut w >@ $sok] where 'shut' is standalone binary of a few lines of C doing the shutdown() on its fd 1. On Windows use TWAPI or ffidl. [kostix] 2009-09-06 [TIP] #332 "Half-Close for Bidirectional Channels" [http://tip.tcl.tk/332] is implemented as part of Tcl 8.6. ---- [Ro] 2007-12-21 : Why does the following line block for a few seconds before returning to the prompt when run from the tclkit console on windows? Is it resolving its own dns name? If so, is there a way around this? socket -server accept -myaddr 127.0.0.1 10001 [UZ] 2007-12-21: I had similar issues with socket clients and servers on the local host, and found that it is due to the antivirus sw (I am using NOD32). After indicating to the AV sw to skip the executable, connection was immediate. Hope it helps. [Ro] 2007-12-21: Thank you, Umberto! I have not played with server sockets on windows in a while and this was unexpected. Your solution worked perfectly, I told the IMON component of NOD32 to skip this tclkit executable I was using and now it works fast and smooth. Many thanks! ---- [KL] 2008-05-02: I just wondered why under Windows XP (with SP2), multiple socket connection were not working like they do under Linux/WIN2000. After searching for some time, I found the solution (just for other people who have the same problem). There is a restriction of maximal half open sockets introduced in Windows XP SP2 to ''increase the security'' against the spreading of worms and virus. I think that's not the proper way to achieve security since that's not the root cause. For more information and a patch to increase the number of connection, please look here [http://www.mydigitallife.info/2005/11/15/windows-xp-sp2-tcp-connection-limit-event-id-4226/] or google for "Event ID 4226". An example script for IP-Scan process can be found at [ipscan]. ---- How is '''socket''' implemented? Under Windows, with WSAAsyncSelect up to 8.5, and through I/O completion ports starting with 8.6 [[confirm]]. Unix has always (well, since what I remember as 7.5) used '''select()'''. ---- See also [Automatic Reconnect Client Sockets], [EasySocket], [Remote debugging via socket], [tclsockets], [tclsock]. ---- !!!!!! [Tcl syntax help] — [Arts and crafts of Tcl-Tk programming] %| [Category Command] | [Category Networking] | [Category Channel] |% !!!!!!