TCP客戶端/伺服器網路程式設計------多程序併發模型(附帶實現)
阿新 • • 發佈:2019-02-14
多程序併發模型
相比同步阻塞迭代模型,多程序併發模型可以避免是程式阻塞在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); } }