📄 sockets.tex
字号:
will be registered with its PortMaster; clients need {\em not} use specified-port mode to connect (ie.~they may set \verb`mode` to \verb`"c"`) so long as they specify the correct name of the server. PortMaster sharing (by setting the environment variable \verb`PMSHARE`) causes servers to work with the {\em\small PMSHARE\/}-specified machine's PortMaster. Clients should use the name of the machine that the {\em PortMaster} is on; the eventual connection will be made with the appropriate server program, even though it is running on~a~different machine than the PortMaster it uses. See Example~\ref{pmsharing} for an illustration of how PortMaster sharing works.\item[Socket *Sopenv(char *srvrname,char *ctrl,char *envvar)] \ \\ The {\em Sopenv} function is used to open client Sockets, but is formulated to resemble the {\em Sopen} function with one additional argument. Assuming your computer system supports the concept of environment variables, the Sopenv function can use an environment variable of your choice to help it open~a~client. Typically,~a~{\small SKTPATH} environment variable gets set up by the user with~a~colon-separated list of machine names (ex. setenv {\small SKTPATH} ``gryphon:dragon:xorn''). The Sopenv function attempts to open~a~client to~a~server of the given name on the current machine first, and then attempts to do so on each machine in the given sequence. If \verb`env_var` is NULL or~a~null string, then \verb`SKTPATH` will be used instead. If successful,~a~Socket pointer is returned, otherwise~a~{\small NULL} Socket pointer is returned. Please see Saccept on how to use servers.\item[int Speek(Socket *skt, char *buf, int buflen)] \ \\ The {\em Speek} function behaves like Sread --- up to {\em buflen} bytes, the buffer will be filled by whatever is currently on the Socket. This function does not remove those bytes from the Socket, however, and those bytes will be returned again on subsequent Speek, Sread, etc.\ calls. This function does \underline{not} block (aka hang, sleep). It will return EOF on select error, some negative number on recv error, zero if no data is present on the Socket, and~a~positive count of the available bytes otherwise. In the latter case, {\em buf} will have~a~copy of the bytes available. {\small MS-DOS}: Speek will only return~a~1 when data is available on the Socket, not the number of bytes available. Furthermore, the buffer {\em buf} will be~a~zero-length string with just~a~null byte.\item[unsigned long Speeraddr(Socket *skt)] \ \\ The {\em Speeraddr} function returns the internet address of the peer Socket.\item[char *Speername(Socket *skt)] \ \\ The {\em Speername} function returns the name of the peer Socket. Internally, it has three buffers; thus it can be used up to three times in the same printf statement.\item[void Sprintf(Socket *skt, char *fmt,...)] \ \\ The {\em Sprintf} function acts in an analogous fashion to fprintf, sprintf, etc, by putting formatted strings, appropriately null byte terminated, through the Socket. Thus, one may use either {\em Sgets} or an appropriate {\em Sscanf} to receive the information.\item[char *Sprtskt(Socket *skt)] \ \\ The {\em Sprtskt} function returns~a~string describing the Socket.\item[void Sputs(char *buf, Socket *skt)] \ \\ The {\em Sputs} function puts~a~null byte terminated string on the Socket in~a~fashion analogous to fputs.\item[int Sread(Socket *skt, char *buf, int buflen)] \ \\ The {\em Sread} function is similar to the {\em read} function in Unix. This function can block (aka hang, sleep) if nothing is on the Socket. Otherwise, it will return up to {\em buflen} bytes in the buffer ``{\em buf}''. This function will return whatever is on the Socket, and doesn't try to insure that buflen bytes are read. It returns the number of bytes read from the Socket. On error, an EOF is returned.\item[int Sreadbytes(Socket *skt, char *buf, int buflen)] \ \\ The {\em Sreadbytes} function behaves much like Sread, and it too can block (aka hang, sleep) if nothing is on the Socket. However, it will not return until buflen bytes are read from the Socket and placed in ``buf''. On error, an EOF is returned.\item[int Srmsrvr(char *skthost)] \ \\ The {\em Srmsrvr} function is made available to take care of those situations when {\small skt = Sopen(``servername'',``s'')} fails because the servername has been inadvertently left in the PortMaster's PortTable. This untoward event can happen, for example, when~a~process is aborted/exited without calling Sclose on its server(s). The Srmsrvr function will remove~a~server (or server@host) from the PortMaster's PortTable. Note: it will \underline{not} close the associated Socket, nor free up any Socket memory, and is \underline{not}~a~substitute for Sclose. The {\em Srmsrvr} function will return either {\small PM\_OK} (if successful) or {\small PM\_SORRY} (otherwise).\item[int Sscanf(Socket *skt, char *fmt, ...)] \ \\ The {\em Sscanf} function acts much the same as sscanf and fscanf, taking format strings and additional arguments in~a~like manner. The arguments Sscanf takes, of course, must all be appropriate pointers. This function will block if insufficient data is available on the socket according to the {\em fmt}. The {\em Sscanf} function returns the number of arguments for which it read data, which may be zero or incomplete if~a~socket error occurred. Normally, the returned count should equal the number of arguments with which Sscanf was provided.\item[int Stest(Socket *skt)] \ \\ The {\em Stest} function allows one to determine if anything is available on the specified Socket, {\em without blocking}. It will return EOF on select error, some negative number on recv error, zero if no data is present on the Socket, and~a~positive count of the available bytes otherwise. {\small MS-DOS}: Stest will only return~a~1 when data is available on the Socket, not the number of bytes available.\item[int Stimeoutwait(Socket *skt,long seconds,long useconds)] \ \\ The {\em Stimeoutwait} function blocks on the given Socket, but for no longer than the number of seconds plus the number of microseconds specified. The function returns the number of bytes available on the Socket (which may be zero), -1 if there was an error, and -2 on timeout.\item[int Svprintf(Socket *skt, char *fmt, void *args)] \ \\ The {\em Svprintf} function reads bytes using~a~printf family format string from the Socket. As each format code is processed, the associated argument is changed in the {\em args} vector. It returns the number of format items processed.\item[int Swait(Socket *skt)] \ \\ The {\em Swait} function will block (aka hang, sleep) until the specified Socket has data available. It will return EOF on select error, some negative number on recv error, zero if no data is present on the Socket, and~a~positive count of the available bytes otherwise.\item[int Swrite(Socket *skt, char *buf, int buflen)] \ \\ The {\em Swrite} function will write {\em buflen} bytes from the {\em buf} buffer onto the specified Socket. The function will return~a~count of the number of bytes transmitted through the Socket, which should be equal to {\em buflen}. If the output is less than {\em buflen}, then an error occurred while writing to the Socket.\end{description}\subsection{Hints}The {\em Hints} below have been found useful at the Intelligent RoboticsLaboratory at the Goddard Space Flight Center. They are based on almosta~year's experience with the \SSL.\begin{enumerate} \item The ``Sscanf'' function is dangerous. It will block until all of the format codes in its {\em fmt} string have been used. If somehow ~a~programmer sends an improper string and Sscanf is used to receive it, then the receiving program will probably hang for quite~a~while. Dr.~Campbell has found that it is somewhat safer to use {\em Sgets} to get an entire string from the Socket and then use {\em sscanf} and {\em stpnxt} to parse it. \item Polling is unfriendly to other processes -- it wastes~a~tremendous amount of {\small CPU} time merely querying the Socket(s) to see if anything is awaiting action. The various blocking functions are much better: Swait, Stimeoutwait, Smask{\small XXX}, etc. \item Unless your processes will always run on the same kind of machine, portability considerations argue against using Sread and Swrite to move non-character string data around -- ie. floats, doubles, and even ints. Even if the programmer tests out the machines and verifies that (s)he can safely move, say,~a~double around, or even~a~vector of doubles, data structures (\verb`struct XXX { ... }`) may have ``holes'' in them placed there for word or byte alignment reasons. These ``holes'' may not be there (or may be placed differently) by other machines and compilers. \item The Srmsrvr function is~a~rather rude function -- there is no ownership check of~a~server. Please use your process name (or your id) as part of your server name so that servers do not clash. Remember: your server's name is in only one ``name space'' shared by all users on your machine. \item For those of you who wish to use other services (ex.~serial ports) which can use the {\em select} function provided by \TCP, check out Smaskfdset and its mate, Smaskunfdset. \item The \IRL\ has been using~a~leading two character command convention: \\ \verb`tp~L~x~y~z rx ry rz` will tell the ``left'' T3 robot to move to ``x~y~z'' (inches) in space with an orientation of ``rx ry rz'' degrees (roll, pitch, yaw). Longer words provide more readability but take up more bandwidth. Experimentally, Dr.~Campbell has found that \TCP\ can transfer about 10,000 packets per second with up to 128 bytes in a packet. Loaded systems will, of course, achieve less throughput. \item It is~a~good idea for clients to inform servers that they are quitting. The \IRL\ has used the following convention: \verb`tq` {\em t\/}ells the server that the messaging client is {\em q\/}uitting. Also,~a~\verb`tQ` tells the server to shut itself down. The server then emits~a~\verb`tq` to all of its clients to inform them that the server is shutting down (except for the one client who issued the shutdown command), and then closes itself down with Sclose. \item The server-client relationship is intimately involved with object-oriented messaging -- refer to the literature on object-oriented concepts. \item The \SSL\ can be used to support~a~{\em no startup sequencing} paradigm. Typically, clients who attempt to Sopen and fail should go into a poll - sleep loop: \begin{example} Client Socket Polling \\ \label{client-polling} \verb` skt= Sopen("servername","c");` \\ \verb` while(!skt) {` \\ \verb` sleep(1);` \\ \verb` skt= Sopen("servername","c");` \\ \verb` }` \end{example} The {\em multiskt.c} program illustrates how servers should be able to accept multiple clients using blocking judiciously. This non-sequencing approach allows one to bring up programs which have servers and/or clients without worrying about what comes first. For two programs, this isn't terribly serious, but at the \IRL\ numerous programs providing numerous services are available and sequencing would be~a~nightmare. \item As alluded to earlier, clients should tell servers and servers should tell clients when they are going down. The program that is {\em not} quitting should return to an ``awaiting another client (or server)'' mode (ie.~see the preceding item). Thus,~a~troublesome program can be brought down, the programs to which it is communicating will gracefully terminate their connections, and the programmer can then (hopefully) fix the problem. When the program is restarted, the non-sequencing approach will allow the program to seamlessly re-enter into communications with the other software. \item When~a~machine is down, and an attempt to connect~a~client Socket using either {\em Sopen\/} directly or {\em Sopenv\/} to~a~server either normally or possibly on that machine, the Sopen will fail but will take an inordinately long time doing so (connection timeout). \item When~a~program dies abruptly, connected Sockets appear to {\em select}() to have something on them (select is used by Stest, Smasktest, Swait, Smaskwait, Speek, Stimeoutwait). Hence, functions which normally block (Smaskwait, Swait) no longer block. On computers which can {\small MSG\_PEEK} (Unix, Vms), the Stest, Speek, Sgets, and Sscanf functions will detect this situation and will return an error indication ({\small EOF}, {\small NULL} pointer, incomplete argument processed count) to indicate that the Socket has~a~problem (one should then Sclose the affected Socket). Furthermore, attempts to write to such dead Sockets may generate {\small SIGPIPE}s on Unix boxes. Unix programmers should write and install signal handlers for {\small SIGPIPE}s. \item For multiple concurrent Sockets, one should generate routines for both closing and opening them.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -