C Socket Programming Tutorial
SHARE Session 5959
Writing Client/Server Programs in C Using Sockets (A Tutorial) Part II Session 5959 Greg Granger
[email protected] SAS/C & C++ Support SAS Institute Cary, NC SAS Institute Inc Cary, NC
SAS/C & C++ Compiler R&D
Slide 1 Feb 1998
C Socket Programming Tutorial
SHARE Session 5959
Remote Execution Sample Program U U U U U U U U U
Remote Execution Connection Diagram getservbyname() coding rexec() function declaration gethostbyname() and struct hostent rexec() caller source code examination System call return conventions Socket address structures and conventions recv() and send() conventions File descriptor sets and select()
SAS Institute Inc Cary, NC
SAS/C & C++ Compiler R&D
Slide 2 Feb 1998
C Socket Programming Tutorial
SHARE Session 5959
Remote Execution Connection Diagram Client issues: rexec server.unx mark mypass ls -l server.unx
host.mvs
rexeccmd
Primary Socket
stdout stdin
rexec
exec cmd (ls -l) stderr (pipe)
Secondary Socket
rexecd <parent>
SAS Institute Inc Cary, NC
SAS/C & C++ Compiler R&D
Slide 3 Feb 1998
C Socket Programming Tutorial
SHARE Session 5959
REXEC Initial Connection host.mvs
server.unx
inetd
rexeccmd rexec
Primary Socket
rexecd
rexecd issues: client issues: rexeccmd.c socket() [53] getservbyname() bind() [60] rexec() listen() rexec.c select() [61] gethostbyname() accept() [70] socket() [79] connect() SAS Institute Inc Cary, NC
SAS/C & C++ Compiler R&D
Slide 4 Feb 1998
C Socket Programming Tutorial
SHARE Session 5959
getservbyname() Coding getservbyname() returns NULL for failure or a pointer to this structure for success:
struct servent { char *s_name; char **s_aliases; int s_port; char *s_proto; };
/* /* /* /*
official name */ array of aliases */ well-known port */ protocol to use (udp/tcp) */
On UNIX the data comes from the “/etc/services” file formatted like the following:
exec login who
SAS Institute Inc Cary, NC
512/tcp 513/tcp 513/udp
whod
# # #
remote remote remote
execution login who and uptime
SAS/C & C++ Compiler R&D
Slide 5 Feb 1998
C Socket Programming Tutorial
SHARE Session 5959
rexec() Function Declaration int rexec(
/* Returns primary socket
*/
char **host,
/* Pointer to hostname by /* reference
*/ */
int port,
/* Port for rexecd server
*/
char *username,
/* Username on remote host
*/
char *passwd,
/* Password on remote host
*/
char *cmd,
/* Command to execute
*/
int *ptr_secondary
/* Place to store secondary */
SAS Institute Inc Cary, NC
SAS/C & C++ Compiler R&D
Slide 6 Feb 1998
C Socket Programming Tutorial
SHARE Session 5959
gethostbyname() Coding Gethostbyname() returns NULL for failure or a pointer to this structure for success: Struct hostent { char *h_name; char **h_aliases; int h_addrtype; int h_length; char **h_addr_list; #define h_addr h_addr_list[0]};
/* /* /* /* /* /*
Official name */ array of aliases */ AF_INET for TCP/IP */ sizeof(struct in_addr) for TCP/IP */ points to array of struct in_addr */ Primary IP address */
Here is an example of printing the IP address: struct hostent *he; char * host = ”ahost.unx.sas.com"; struct in_addr *ia; he = gethostbyname(host); ia = (struct in_addr *)(he->h_addr); printf("IP address: %s\n",inet_ntoa(*ia));
SAS Institute Inc Cary, NC
SAS/C & C++ Compiler R&D
Slide 7 Feb 1998
C Socket Programming Tutorial
SHARE Session 5959
“struct hostent” diagram char[] tools.sas.com Struct hostent
array of char *
char *h_name
char[] bigserver.sas.com
char **h_aliases int
h_addrtype
int
h_length
AF_INET 4
0 array of char *
char **h_addr_list
0
SAS Institute Inc Cary, NC
char[] server1.sas.com
SAS/C & C++ Compiler R&D
struct in_addr 149.179.3.3 struct in_addr 154.166.17.231 Slide 8 Feb 1998
C Socket Programming Tutorial
SHARE Session 5959
System Call Return Conventions U U U
U
Most system calls have the same return conventions An int value >= 0 indicates success; -1 indicates failure. Failed calls set “errno” to indicate the cause of failure; perror() will print a message based on the “errno” value. Here is the typical coding logic: int s = socket(AF_INET, SOCK_STREAM, 0); if (s < 0) { perror(“socket() failed”); exit(EXIT_FAILURE); }
SAS Institute Inc Cary, NC
SAS/C & C++ Compiler R&D
Slide 9 Feb 1998
C Socket Programming Tutorial
SHARE Session 5959
Socket Address Structures Socket address formats vary. Each format is called an “addressing family”. The generic format is: struct sockaddr { u_short sa_family; /* Addressing family */ char sa_data[14]; }; /* varies */ AF_INET is the addressing family for TCP/IP. It’s format is: struct in_addr { u_long s_addr; }; /* net byte order */ struct sockaddr_in { short sin_family; u_short sin_port; struct in_addr sin_addr; char sin_zero[8]; }; SAS Institute Inc Cary, NC
/* /* /* /*
AF_INET */ TCP or UDP port */ IP address */ varies */
SAS/C & C++ Compiler R&D
Slide 10 Feb 1998
C Socket Programming Tutorial
SHARE Session 5959
Socket Address Conventions U U U
U
For connect(), the port and IP address must be specified. For bind(), either may be set to zero. Specifying “sin_port” as zero requests that the system assign a transient port. Use getsockname() to find out what port number was chosen. Specifying “sin_addr” as zero binds to all IP addresses on the host (some hosts have more than one).
SAS Institute Inc Cary, NC
SAS/C & C++ Compiler R&D
Slide 11 Feb 1998
C Socket Programming Tutorial
SHARE Session 5959
inetd Create Server Program host.mvs
server.unx
inetd
rexeccmd rexec
fork() Primary Socket
exec()
rexecd
rexec.c lines [79 - 82]
Server creation program (inetd) issues a fork() and exec() call to start rexecd. The socket descriptor is attached to stdin, stdout and stderr of rexecd. SAS Institute Inc Cary, NC
SAS/C & C++ Compiler R&D
Slide 12 Feb 1998
C Socket Programming Tutorial
SHARE Session 5959
Server Creation Socket Close host.mvs
server.unx
inetd rexeccmd rexec
Primary Socket
close()
rexecd
rexec.c lines [79 - 82]
Server creation program (inetd) issues a close() to close it’s connection to the socket, then waits for a new client connection. SAS Institute Inc Cary, NC
SAS/C & C++ Compiler R&D
Slide 13 Feb 1998
C Socket Programming Tutorial
SHARE Session 5959
Client Establishes stderr port host.mvs
server.unx
rexeccmd rexec
Primary
stdin/stdout/stderr
Socket
rexecd
rexec.c lines [83 - 140]
Rexecd reads stdin until a null character is found, if any characters are read before the null they are interpreted as an optional secondary port address to be used for stderr. SAS Institute Inc Cary, NC
SAS/C & C++ Compiler R&D
Slide 14 Feb 1998
C Socket Programming Tutorial
SHARE Session 5959
recv() and send() conventions U U U
U
recv() returns 0 for EOF; >0 for number of bytes read recv() often returns fewer bytes than requested; call recv() in a loop until you have gotten them all For TCP, send() does not create record boundaries; recv() may get the result of more or less than one send() recv()/send() behavior is a common programming error with TCP/IP and socket programming.
SAS Institute Inc Cary, NC
SAS/C & C++ Compiler R&D
Slide 15 Feb 1998
C Socket Programming Tutorial
SHARE Session 5959
rexecd connect() stderr Port host.mvs
server.unx
rexeccmd rexec
Primary Socket
stdin/stdout
rexecd
stderr
rexec.c lines [83 - 140]
Secondary Socket
Rexecd connects stderr to port created and specified by rexec. Stderr is used to return error information to rexec and to send signal requests (kill calls) to rexecd. SAS Institute Inc Cary, NC
SAS/C & C++ Compiler R&D
Slide 16 Feb 1998
C Socket Programming Tutorial
SHARE Session 5959
Send user, password and command host.mvs
server.unx
rexeccmd rexec
Primary Socket
stdin/stdout
rexecd
stderr
rexec.c lines [141 - 150]
Secondary Socket
Client rexec writes the userid, password and command to execute to the primary socket, where rexecd receives them via reads of the primary socket (which is stdin). SAS Institute Inc Cary, NC
SAS/C & C++ Compiler R&D
Slide 17 Feb 1998
C Socket Programming Tutorial
SHARE Session 5959
Server confirms host.mvs
server.unx
rexeccmd rexec
Primary Socket
stdin/stdout
rexecd
stderr
rexec.c lines [152 - 171] rexec exits line [176]
Secondary Socket
Server rexecd writes a one byte value of binary zero to the primary socket (stdout) if authorization is successful, otherwise it writes a one byte value of binary one. Client rexec receives this via a read of the primary socket SAS Institute Inc Cary, NC
SAS/C & C++ Compiler R&D
Slide 18 Feb 1998
C Socket Programming Tutorial
SHARE Session 5959
Server creates command executor host.mvs
server.unx stdin Primary Socket
rexeccmd
stdout
Secondary Socket
child
stderr (pipe) stderr
rexeccmd lines [61-118]
rexecd
rexecd
parent
rexecd creates a pipe (for stderr) then forks creating a child process in which to run the command. Note that rexecd closes it’s connection to the primary socket and that the child process closes it’s connection to the secondary socket. SAS Institute Inc Cary, NC
SAS/C & C++ Compiler R&D
Slide 19 Feb 1998
C Socket Programming Tutorial
SHARE Session 5959
Child Process Executes Command host.mvs
server.unx stdin Primary Socket
rexeccmd
stdout
Secondary Socket
child
stderr (pipe) stderr
rexeccmd lines [61-118]
command
rexecd
parent
The child process then configures it’s environment to match the userid and runs the command using the execl call. Output from the command is sent to rexeccmd through the primary socket. SAS Institute Inc Cary, NC
SAS/C & C++ Compiler R&D
Slide 20 Feb 1998
C Socket Programming Tutorial
SHARE Session 5959
File Descriptor Sets U U U U
A file descriptor is an integer [returned by open() or socket()] which identifies a file or socket. Descriptors are numbered 0 through FD_SETSIZE-1 “fd_set” is a type which contains a bit for each descriptor The following macros manipulate file descriptor sets: #include <sys/types.h> int desc; fd_set fds; FD_ZERO(&fds); /* FD_CLR(desc, &fds); /* FD_SET(desc, &fds); /* FD_ISSET(desc, &fds); /*
SAS Institute Inc Cary, NC
zero entire set clear desc bit set desc bit test desc bit
SAS/C & C++ Compiler R&D
*/ */ */ */
Slide 21 Feb 1998
C Socket Programming Tutorial
SHARE Session 5959
The select() call U
The select() system call awaits activity on descriptor sets int select( int nfds, fd_set *read, fd_set *write, fd_set *except, struct timeval *timeout
U U U
/* /* /* /* /* /*
returns number active highest desc used + 1 Await read on these await write on these seldom used inactivity timeout
*/ */ */ */ */ */
A “timeout” parameter of NULL specifies indefinite waiting A zero time value sets select() non-blocking A non-zero time value, sets a maximum wait time
SAS Institute Inc Cary, NC
SAS/C & C++ Compiler R&D
Slide 22 Feb 1998
C Socket Programming Tutorial
SHARE Session 5959
Summary U U U U
Reviewed various socket API function calls REXEC / REXECD dialog Useable TCP/IP Socket Application Questions ?
SAS Institute Inc Cary, NC
SAS/C & C++ Compiler R&D
Slide 23 Feb 1998
C Socket Programming Tutorial
SHARE Session 5959
Bibliography U
U U U U U
Internetworking with TCP/IP: Volumes I, II & III, Douglas Comer, Prentice Hall, 1991 (ISBN Vol I: 0134685059, Vol III: 0138487146) The Whole Internet User’s Guide & Catalog by Ed Kroll; O’Reilly & Associates UNIX Network Programming by W. Richard Stevens; Prentice Hall, 1990 (ISBN 0139498761) Socket API Programmer’s Reference UNIX “man” pages TCP/IP Illustrated: Volumes 1 & 2, W. Richard Stevens (v2 with Gary R. Wright); Addison-Wesley Publishing Company, 1994
SAS Institute Inc Cary, NC
SAS/C & C++ Compiler R&D
Slide 24 Feb 1998