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网络编程之多进程多线程的主要内容,如果未能解决你的问题,请参考以下文章