UNIX网络编程卷1(第三版) 客户/服务器程序示例

2020-08-31 14:58:55 浏览数 (2)

1.TCP回射服务器程序:main函数

代码语言:javascript复制
#include	"unp.h"

int
main(int argc, char **argv)
{
	int					listenfd, connfd;
	pid_t				childpid;
	socklen_t			clilen;
	struct sockaddr_in	cliaddr, servaddr;
	void				sig_chld(int);

	listenfd = Socket(AF_INET, SOCK_STREAM, 0);

	bzero(&servaddr, sizeof(servaddr));
	servaddr.sin_family      = AF_INET;
	servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
	servaddr.sin_port        = htons(SERV_PORT);

	Bind(listenfd, (SA *) &servaddr, sizeof(servaddr));

	Listen(listenfd, LISTENQ);

	Signal(SIGCHLD, sig_chld);

	for ( ; ; ) {
		clilen = sizeof(cliaddr);
		if ( (connfd = accept(listenfd, (SA *) &cliaddr, &clilen)) < 0) {
			if (errno == EINTR)
				continue;		/* back to for() */
			else
				err_sys("accept error");
		}

		if ( (childpid = Fork()) == 0) {	/* child process */
			Close(listenfd);	/* close listening socket */
			str_echo(connfd);	/* process the request */
			exit(0);
		}
		Close(connfd);			/* parent closes connected socket */
	}
}

创建TCP套接字。在待绑定到该套接字的网际网套接字地址结构中填入通配地址(INADDR_ANY)和服务器众所周知的端口(SERV_PORT).捆绑通配地址是告诉系统:要是系统是多宿主机,我们将接受目的地址为任何本地接口的连接。listen把该套接字转成一个监听套接字。

服务器阻塞于accept调用,等待客户端连接完成。

fork为每个客户派生给一个处理它们的子进程。子进程关闭监听套接字,父进程关闭已连接的套接字。。子进程调用str_echo处理客户。

代码语言:javascript复制
#include "unp.h"

void
str_echo(int sockfd)
{
    ssize_t n;
    char buf[MAXLINE];

again:
    while((n=read(sockfd,buf,MAXLINE))>0)
        Writen(sockfd,buf,n);
    if(n<0&&errno==EINTR)
        goto again;
    else if(n<0)
        errr_sys("str_echo:read error");
}

read函数从套接字读入数据,writen函数把其内容回射给客户。如果客户关闭连接,那么接收到客户的FIN将导致服务器子进程的read函数返回0,这又导致str_echo函数的返回,从而终止子进程。

2.TCP回射客户程序:main函数

代码语言:javascript复制
/* Use standard echo server; baseline measurements for nonblocking version */
#include	"unp.h"

int
main(int argc, char **argv)
{
	int					sockfd;
	struct sockaddr_in	servaddr;

	if (argc != 2)
		err_quit("usage: tcpcli <IPaddress>");

	sockfd = Socket(AF_INET, SOCK_STREAM, 0);

	bzero(&servaddr, sizeof(servaddr));
	servaddr.sin_family = AF_INET;
	servaddr.sin_port = htons(7);
	Inet_pton(AF_INET, argv[1], &servaddr.sin_addr);

	Connect_timeo(sockfd, (SA *) &servaddr, sizeof(servaddr), 10);

	str_cli(stdin, sockfd);		/* do it all */

	exit(0);
}

3.POSIX信号处理

信号就是告知某个进程发生了某个事件的通知,有时候也称为软件中断,信号通常是异步的,也就是进程预先不知道信号的准确发生时刻。

信号可以:由一个进程发给另一个进程或者自身;由内核发给某个进程。

每个信号都有一个与之关联的处置,也称为行为。

0 人点赞