并发服务器:
(1)多进程并发服务器:http://blog.csdn.net/songshimvp1/article/details/51819765
示例:http://blog.csdn.net/songshimvp1/article/details/51833781
(2)I/O复用并发服务器:http://blog.csdn.net/songshimvp1/article/details/51842689
示例:http://blog.csdn.net/songshimvp1/article/details/51842236
(3)多线程并发服务器:http://blog.csdn.net/songshimvp1/article/details/51895311
(以下程序只是展示说明,还未验证,待更新......)
1、多线程并发服务器框架:
2、多线程并发服务器程序:
static void *doit(void *); /* each thread executes this function */
int main(int argc, char **argv)
{
int listenfd, *iptr;
thread_t tid;
socklen_t addrlen, len;
struct sockaddr *cliaddr;
if (argc == 2)
listenfd = Tcp_listen(NULL, argv[1], &addrlen);
else if (argc == 3)
listenfd = Tcp_listen(argv[1], argv[2], &addrlen);
else
err_quit("usage: tcpserv01 [ ] ");
cliaddr = Malloc(addrlen);
for ( ; ; ) {
len = addrlen;
iptr = Malloc(sizeof(int)); // malloc 存放待accept返回的已连接描述符(使得每个线程都有自己的已连接描述符的副本)
*iptr = Accept(listenfd, cliaddr, &len);
Pthread_create(&tid, NULL, &doit, iptr); // 调用Pthread_create代替fork
// 主进程不关闭已连接套接字(同一进程的所有子线程共享全部描述符,如果主线程调用close,就会终止连接)
// 创建子线程并不影响已打开的描述符的引用计数,这一点不同于fork
}
}
static void *
doit(void *arg)
{
int connfd;
connfd = *((int *) arg);
free(arg);
Pthread_detach(pthread_self()); //首先让自身脱离
str_echo(connfd); /* same function as before */
Close(connfd); /* done with connected socket */
return(NULL);
}
3、多线程并发服务器客户端程序:
#include "unp.h"
#include "unpthread.h"
void *copyto(void *);
// 最好是把下面两个值放在一个struct中,然后把指向该struct的一个指针作为参数传递给我们将要创建的线程
static int sockfd; // 连接到服务器的TCP套接字描述符 /* global for both threads to access */
static FILE *fp; // 输入文件的标准I/O库FILE指针
void str_cli(FILE *fp_arg, int sockfd_arg)
{
char recvline[MAXLINE];
pthread_t tid;
sockfd = sockfd_arg; /* copy arguments to externals */
fp = fp_arg;
Pthread_create(&tid, NULL, copyto, NULL); // 创建线程
while (Readline(sockfd, recvline, MAXLINE) > 0)
Fputs(recvline, stdout);
}
void * copyto(void *arg)
{
char sendline[MAXLINE];
while (Fgets(sendline, MAXLINE, fp) != NULL)
Writen(sockfd, sendline, strlen(sendline)); // 把读自标准输入的每个文本行复制到套接字
Shutdown(sockfd, SHUT_WR); // 读得EOF,发送FIN /* EOF on stdin, send FIN */
return(NULL);
/* 4return (i.e., thread terminates) when EOF on stdin */
}
int main(int argc, char **argv)
{
int sockfd;
struct sockaddr_in servaddr;
if (argc != 2)
err_quit("usage: tcpcli ");
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));
str_cli(stdin, sockfd); /* do it all */
exit(0);
}