进程 tcp 多进程 并发
#include <header.h>
#define SER_PORT 8888
#define SER_IP "192.168.125.192"
void handle(int signum)
{
if(signum==SIGCHLD)
{
while(waitpid(-1,NULL,WNOHANG)>0);
}
}
int main(int argc, const char *argv[])
{
//将子进程的SIGCHLD(17)信号
//当子进程退出时,会向其父进程发送该信号
if(signal(SIGCHLD,handle)==SIG_ERR)
{
perror("signal");
return -1;
}
//为进程创建一个端点
int sfd=socket(AF_INET,SOCK_STREAM,0);
if(sfd==-1)
{
perror("socket");
return -1;
}
printf("socket success! sfd=%d\n",sfd);
//端口号快速重用
int reuse=1;
if(setsockopt(sfd,SOL_SOCKET,SO_REUSEADDR,&reuse,sizeof(reuse))==-1)
{
perror("setsockopt error");
return -1;
}
//准备地址信息结构体
struct sockaddr_in sin;
sin.sin_family=AF_INET;
sin.sin_port=htons(SER_PORT);
sin.sin_addr.s_addr=inet_addr(SER_IP);
//绑定地址信息
if(bind(sfd,(struct sockaddr*)&sin,sizeof(sin))==-1)
{
perror("bind");
return -1;
}
printf("bind success!\n");
//将套接字设置成被动监听状态
if(listen(sfd,128)==-1)
{
perror("listen");
return -1;
}
printf("listen success!\n");
//阻塞等待客户端的连接
//定义用于接收客户端信息的容器
struct sockaddr_in cin;
socklen_t addrlen=sizeof(cin);
int newfd=-1;
while(1)
{
newfd=accept(sfd,(struct sockaddr*)&cin,&addrlen);
if(newfd==-1)
{
perror("accept");
return -1;
}
printf("[%s:%d]:发来连接请求\n",inet_ntoa(cin.sin_addr),ntohs(cin.sin_port));
//创建子进程
pid_t pid=fork();
if(pid>0)
{
//关闭newfd
close(newfd);
}
else if(pid==0)
{
//关闭sfd
close(sfd);
//与客户端进行相互通信
char rbuf[128]={0}; //读取消息内容的容器
while(1)
{
//清空容器
bzero(rbuf,sizeof(rbuf));
//从套接字中读取数据
//int res=read(newfd,rbuf,sizeof(rbuf));
int res=recv(newfd,rbuf,sizeof(rbuf),0);
if(res==0)
{
printf("客户端已经下线\n");
break;
}
//将读取的消息展示出来
printf("[%s:%d]:%s\n",inet_ntoa(cin.sin_addr),ntohs(cin.sin_port),rbuf);
//将收的的消息处理一下,回复给客户端
strcpy(rbuf,"^_^");
//write(newfd,rbuf,strlen(rbuf));
send(newfd,rbuf,strlen(rbuf),0);
printf("发送成功\n");
}
//关闭套接字
close(newfd);
//退出子进程
exit(EXIT_SUCCESS);
}
else
{
perror("fork");
return -1;
}
}
close(sfd);
return 0;
}
线程 tcp 多线程并发
#include <header.h>
#define SER_PORT 8888
#define SER_IP "192.168.125.192"
//定义一个像线程体函数传参的结构体
struct Info
{
int newfd;
struct sockaddr_in cin;
};
//定义线程函数
void *deal_cli_msg(void *arg)
{
//解析传过来的数据
int newfd=((struct Info*)arg)->newfd;
struct sockaddr_in cin=((struct Info*)arg)->cin;
//与客户端进行通信
char buf[128]={0};
while(1)
{
//清空容器
bzero(buf,sizeof(buf));
//从套接字中读取数据
int res=recv(newfd,buf,sizeof(buf),0);
if(res==0)
{
printf("客户端已下线\n");
break;
}
//将读取的消息展示出来
printf("[%s:%d]:%s\n",inet_ntoa(cin.sin_addr),ntohs(cin.sin_port),buf);
//将收到的消息处理一下,回复给客户端
strcat(buf,"^_^");
//将消息发送给客户端
send(newfd,buf,strlen(buf),0);
printf("发送成功\n");
}
//关闭套接字
close(newfd);
//退出线程
pthread_exit(NULL);
}
int main(int argc, const char *argv[])
{
//为通信创建一个端点
int sfd=socket(AF_INET,SOCK_STREAM,0);
if(sfd==-1)
{
perror("socket");
return -1;
}
printf("socket success! sfd=%d\n",sfd);
//准备服务器地址信息结构体
struct sockaddr_in sin;
sin.sin_family=AF_INET;
sin.sin_port=htons(SER_PORT);
sin.sin_addr.s_addr=inet_addr(SER_IP);
//绑定服务器地址信息
if(bind(sfd,(struct sockaddr*)&sin,sizeof(sin))==-1)
{
perror("bind");
return -1;
}
printf("bind success!\n");
//将套接字设置成被动监听状态
if(listen(sfd,128)==-1)
{
perror("listen");
return -1;
}
printf("listen success!\n");
//阻塞等待客户端连接
//定义接收客户端信息的结构体容器
struct sockaddr_in cin;
socklen_t addrlen=sizeof(cin);
while(1)
{
//accept函数会与选一个当前未分配的最小的文件描述符
//即使在阻塞过程中,有更小的文件描述符产生,本次操作的文件描述符也不会更改
int newfd=accept(sfd,(struct sockaddr*)&cin,&addrlen);
if(newfd==-1)
{
perror("accept");
return -1;
}
printf("[%s:%d]:发来连接请求,newfd=%d\n",inet_ntoa(cin.sin_addr),ntohs(cin.sin_port),newfd);
//定义要传递数据的结构体变量
struct Info buf={newfd,cin};
//创建分支线程,用于通信
pthread_t tid=-1;
if(pthread_create(&tid,0,deal_cli_msg,&buf)==-1)
{
printf("pthread_create\n");
return -1;
}
pthread_detach(tid);
}
close(sfd);
return 0;
}