栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 系统运维 > 运维 > Linux

linux网络编程之多进程、多线程

Linux 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

linux网络编程之多进程、多线程

目录

多进程模型

demo 多线程模型

demo

先read 函数的返回值 非常重要

> 0 实际读到的字节数

= 0 已经读到结尾(对端已经关闭)

-1 应进一步判断errno的值:重要!!! -1一定要进行判断,否则接收端一直在接收

	errno = EAGAIN or EWOULDBLOCK 设置了非阻塞方式读,没有数据到达。 

	errno = EINTR 慢速系统调用被 中断。

	errno = “其他情况” 异常。
多进程模型
socket()
bind()
listen()
//catch sigchild signal 回收子进程
while(1)
{
	cfd=accept()
	pid=fork()
	if(pid==0)//child process
	{
		close(lfd)
		read()/write()
	}
	else if(pid > 0)//parent process
	{
		close(cfd)
	}
	else
	{
		//error
	}
}
demo
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include

#define SERVER_PORT 6666 
#define MAXLINE 1024


void catch_child(int signum)
{
	while(waitpid(0,NULL,WNOHANG) > 0);
	return;
}


static void sys_error(const char *str)
{
	perror(str);
	exit(1);
}

int main(int argc,char *argv[])
{
	int lfd = 0,cfd = 0;
	int ret;
	char buffer[BUFSIZ],client_ip[56];
	pid_t pid;
	char str[1024];

	struct sockaddr_in serv_addr,clit_addr;
	socklen_t clit_addr_len,client_ip_len;
	//signal
	struct sigaction act;
	act.sa_handler = catch_child;
	sigemptyset(&act.sa_mask);
	act.sa_flags = 0;
	ret = sigaction(SIGCHLD,&act,NULL);
	if(ret != 0)
	{
		sys_error("sigaction error");
	}

	serv_addr.sin_family = AF_INET;
	serv_addr.sin_port = htons(SERVER_PORT);
	serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);

	lfd = socket(AF_INET,SOCK_STREAM,0);
	if(lfd == -1)
		sys_error("socket error");

	int opt = 1;
	setsockopt(lfd,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(opt));

	bind(lfd,(struct sockaddr *)&serv_addr,sizeof(serv_addr));

	listen(lfd,128);
    socklen_t client_addrlength = sizeof(clit_addr);
	client_addrlength = sizeof(clit_addr);
	
	while(1){
        	cfd = accept(lfd,(struct sockaddr *)&clit_addr,&client_addrlength);
        	if(cfd < 0)
            {
                printf("error is:%dn",errno);
		    }

        	pid = fork();
        	if (pid == 0) {//child
            	close(lfd);
            	while (1) {
                	ret = read(cfd, buffer, MAXLINE);
                	if (ret == 0) {
                    	printf("the other side has been closed.n");
                    	break;
					}
					else if(ret == -1)
					{
						//printf("str=%sn", strerror(errno));
						if (errno == EINTR)
                        		continue;
	            	 	else
                        	return -1;
					}
                write(cfd, buffer, ret);
            }
           	 	close(cfd);
            	return 0;
        	} else if (pid > 0) {//parent
            	close(cfd);
        	}  
			else
			{
		   	 	perror("error exitn");
	            exit(-1);
			}
		}
        return 0;
}
多线程模型
socket()
bind()
listen()
while(1)
{
	cfd = accept(lfd,);
	pthread_create(&pid,NULL,fun,(void* )cfd);
	prhread_detach(tid);//子线程分离
}
//child pthead
void *fun()
{
	read()/write()
	pthread_exit();
}

demo
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include

#define MAXLINE 1024
#define SERV_PORT 6666

struct s_info {                    
    struct sockaddr_in cliaddr;
    int connfd;
};

void *work_pthread(void *arg)
{
    int n,i;
    struct s_info *ts = (struct s_info*)arg;
    char buf[MAXLINE];
    char str[INET_ADDRSTRLEN];     
    
    while (1) {
        n = read(ts->connfd, buf, MAXLINE);                    
        if (n == 0) {
            printf("the client %d closed...n", ts->connfd);
            break;                                             
        } 
        else if(ret == -1)
		{
				//printf("str=%sn", strerror(errno));
				if (errno == EINTR)
                  		continue;
	            else
                        return -1;
		}            
        write(ts->connfd, buf, n);  //回写
    }
    close(ts->connfd);
    return (void *)0;
}

int main(void)
{
    struct sockaddr_in servaddr, cliaddr;
    socklen_t cliaddr_len;
    int listenfd, connfd;
    pthread_t tid;

    struct s_info ts[256]; 
    int i = 0;

    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);     
    
    int opt = 1;
	setsockopt(listenfd ,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(opt));
                                      
    bind(listenfd, (struct sockaddr *)&servaddr, sizeof(servaddr));             
    listen(listenfd, 128);                                                      

    printf("Accepting client connect ...n");

    while (1) {
        cliaddr_len = sizeof(cliaddr);
        connfid = accept(listenfd, (struct sockaddr *)&cliaddr, &cliaddr_len); 
        if(connfid < 0)
		{
			printf("error is %dn",errno);
		}
		ts[i].cliaddr = cliaddr;
        ts[i].connfd = connfd;

        pthread_create(&tid, NULL, work_pthread, (void*)&ts[i]);
        pthread_detach(tid);                                                    
        i++;
    }
    return 0;
}

端口复用,在断开连接后,端口号可以再次被使用,否则要等到40多秒

int opt = 1;
setsockopt(lfd,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(opt));
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/730135.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号