天天看点

Client and Server Code on Network Programming

The best way to learn the sockets interface is to study example code. The code for an echo client is showed below.

#include <stdlib.h>
#include <sys/socket.h>
#include <sys/type.h>

int main(int argc, char **argv)
{
		char *hostname, buf[MAXLINE];
				
		if (argc != 3) {
				fprintf(stderr, "usage: %s <host> <port>\n", argv[0]);
 				exit(0);
 		}
 		hostname = argv[1];
 		int port = atoi(argv[2]);
		
		// Create a socket descriptor
		int clientfd = socket(AF_INET, SOCK_STREAM, 0); // clientfd, Which can use Unix I/O to
								                        // communicate with the server
		// Fill in the server’s IP address and port
		struct hostent *hp;
		struct sockaddr_in serveraddr;
		hp = gethostbyname(hostname);
		bzero((char *) &serveraddr, sizeof(serveraddr));
		serveraddr.sin_family = AF_INET;
		bcopy((char *)hp->h_addr,
		(char *)&serveraddr.sin_addr.s_addr, hp->h_length);
		serveraddr.sin_port = htons(port);
		
		// Establish a connection with the server
		connect(clientfd, (SA *) &serveraddr, sizeof(serveraddr));
		
		rio_t rio;
		rio_readinitb(&rio, clientfd);
 		while (fgets(buf, MAXLINE, stdin) != NULL) {
 				rio_writen(clientfd, buf, strlen(buf));  // Send the textline to the server
 				rio_readlineb(&rio, buf, MAXLINE);       // Read the echo line from the server
 				fputs(buf, stdout);
		}
 		close(clientfd);
 		exit(0);
}
           

After establishing a connection with the server, the client enter a loop that repeatedly reads a text line from standard input, sends the text line to the server, reads the echo line from the server, and prints the result to standard output. The loop terminates when  fgets encounters End-Of-File on standard input, either because the user typed ctrl-d  at the keyboard, or because it has exhausted the text lines in a redirected input file.

      The main routine for the echo server is represented below.

#include <stdlib.h>
#include <sys/socket.h>
#include <sys/type.h>

int main(int argc, char **argv)
{
		if (argc != 2) {
		 		fprintf(stderr, "usage: %s <port>\n", argv[0]);
		 		exit(0);
 		}
 		int port = atoi(argv[1]);
		
		// Create a socket descriptor
		int listenfd = socket(AF_INET, SOCK_STREAM, 0);
		
		// Eliminates "Address already in use" error from bind.
		int optval = 1;
		setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR,
		  					(const void *)&optval , sizeof(int));
		
		// Listenfd will be an endpoint for all requests to port 
		// on any IP address for this host 
		struct sockaddr_in serveraddr;
		bzero((char *) &serveraddr, sizeof(serveraddr));
		serveraddr.sin_family = AF_INET;
		serveraddr.sin_addr.s_addr = htonl(INADDR_ANY);
		serveraddr.sin_port = htons((unsigned short)port);
		bind(listenfd, (SA *)&serveraddr, sizeof(serveraddr));
		
		// Make it a listening socket ready to accept connection requests
		listen(listenfd, LISTENQ);	
		  		
 		struct sockaddr_in clientaddr;
		struct hostent *hp;
 		while (1) {
		 		int clientlen = sizeof(clientaddr);
		 		int connfd = accept(listenfd, (SA *)&clientaddr, &clientlen);
		
		 		// Determine the domain name and IP address of the client
		 		hp = gethostbyaddr((const char *)&clientaddr.sin_addr.s_addr,
		 		sizeof(clientaddr.sin_addr.s_addr), AF_INET);
		 		char *haddrp = inet_ntoa(clientaddr.sin_addr);
		 		printf("server connected to %s (%s)\n", hp->h_name, haddrp);
				
				// Echo that reads and echoes text lines
		 		char buf[MAXLINE];
		 		rio_t rio;
		 		rio_readinitb(&rio, connfd);		
				while((size_t n = rio_readlineb(&rio, buf, MAXLINE)) != 0) {
						printf("server received %d bytes\n", n);
		 				rio_writen(connfd, buf, n);
 				} 
		 		close(connfd);
 		}
 		exit(0);
}
           

After opening the listening descriptor, it enters an infinite loop. Each iteration waits for a connection request from a client, prints the domain name and IP address of the connected client, and performs the echo that services the client. When the echo routine returns, the main routine closes the connected descriptor. Once the client and server have closed their respective descriptors, the connection is terminated.

继续阅读