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.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值