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

Posted 为了维护世界和平_

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了linux网络编程之多进程多线程相关的知识,希望对你有一定的参考价值。

目录

先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<sys/types.h>
#include<sys/socket.h>
#include<arpa/inet.h>
#include<stdio.h>
#include<sys/un.h>
#include<unistd.h>
#include<stdlib.h>
#include<signal.h>
#include<assert.h>
#include<string.h>
#include<ctype.h>
#include<errno.h>
#include<sys/wait.h>
#include<errno.h>

#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:%d\\n",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=%s\\n", 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 exit\\n");
	            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 <stdio.h>
#include <string.h>
#include <arpa/inet.h>
#include <pthread.h>
#include <ctype.h>
#include <unistd.h>
#include <fcntl.h>
#include<errno.h>

#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=%s\\n", 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 %d\\n",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));

以上是关于linux网络编程之多进程多线程的主要内容,如果未能解决你的问题,请参考以下文章

网络编程之多线程——多线程与多进程的区别

网络编程之多线程——守护线程

并发编程之多线程

并发编程之多线程

编程思想之多线程与多进程——Java中的多线程

python 并发编程之多线程