UNIX网络编程——并发服务器(多线程)

并发服务器:

      (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 [ <host> ] <service or port>");

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

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

	exit(0);
}



  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值