1. 程式人生 > >TCP客戶端/伺服器網路程式設計------多程序併發模型(附帶實現)

TCP客戶端/伺服器網路程式設計------多程序併發模型(附帶實現)

多程序併發模型

相比同步阻塞迭代模型,多程序併發模型可以避免是程式阻塞在read系統呼叫上。如果沒有客戶端來建立連線,則會阻塞在accept處。一旦某個客戶端連線建立起來,則立即開啟一個新的程序來處理與這個客戶的資料互動。避免程式阻塞在read呼叫,而影響其他客戶端的連線。

缺陷:

在多程序併發模型中,每一個客戶端連線開啟fork一個程序,雖然linux中引入了寫實拷貝機制,大大降低了fork一個子程序的消耗,但若客戶端連線較大,則系統依然將不堪負重。

程式碼:《UNIX網路程式設計卷1:套接字聯網API》

實現功能:

伺服器

客戶端


1)伺服器端程式碼

main函式
#include	"unp.h"

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

	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);

	for ( ; ; ) {
		clilen = sizeof(cliaddr);
		connfd = Accept(listenfd, (SA *) &cliaddr, &clilen);

		if ( (childpid = Fork()) == 0) {	/* child process */
			Close(listenfd);	/* close listening socket */
			printf("%d\n",connfd);
			str_echo(connfd);	/* process the request */
			exit(0);
		}
		Close(connfd);			/* parent closes connected socket */
	}
}
str_echo函式
#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)
		err_sys("str_echo: read error");
}

2)客戶端程式碼

main函式
#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(SERV_PORT);
	Inet_pton(AF_INET, argv[1], &servaddr.sin_addr);

	Connect(sockfd, (SA *) &servaddr, sizeof(servaddr));

	printf("%d\n",sockfd );

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

	exit(0);
}
str_cli函式
#include	"unp.h"

void
str_cli(FILE *fp, int sockfd)
{
	char	sendline[MAXLINE], recvline[MAXLINE];

	while (Fgets(sendline, MAXLINE, fp) != NULL) {

		Writen(sockfd, sendline, strlen(sendline));

		if (Readline(sockfd, recvline, MAXLINE) == 0)
			err_quit("str_cli: server terminated prematurely");

		Fputs(recvline, stdout);
	}
}