1.多进程(信号)
#include "myhead.h"
#define PORT 2437
#define IP "192.168.125.115"
void handler(int signo){
if(signo==SIGCHLD){
while(waitpid(-1,NULL,WNOHANG)>0);
}
}
//自定义处理客户端函数
int MY_sev(int newfd,struct sockaddr_in cin){
char rbuf[128]="";
while(1){
bzero(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);
strcat(rbuf,":)");
send(newfd,rbuf,sizeof(rbuf),0);
}
close(newfd);
return 0;
}
int main(int argc, const char *argv[])
{
if(signal(SIGCHLD,handler)==SIG_ERR){
perror("signal error");
return -1;
}
int sfd=-1;
if((sfd=socket(AF_INET,SOCK_STREAM,0))==-1){
perror("socket error");
return -1;
}
printf("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(PORT);
sin.sin_addr.s_addr=inet_addr(IP);
if(bind(sfd,(struct sockaddr*)&sin,sizeof(sin))==-1){
perror("bind error");
return -1;
}
printf("bind success_%d_%s_%s\n",__LINE__,__FILE__,__func__);
//3.将套接字设置成被动监听状态
if(listen(sfd,128)==-1){
perror("listen error");
return -1;
}
printf("listen success_%d_%s_%s\n",__LINE__,__FILE__,__func__);
//4.1定义用于接收客户端地址信息的结构体变量
struct sockaddr_in cin;
socklen_t socklen=sizeof(cin);
//4.2接收客户端链接请求
int newfd=-1;
pid_t pid=-1;
while(1){
if((newfd=accept(sfd,(struct sockaddr*)&cin,&socklen))==-1){
perror("accept error");
return -1;
}
printf("[%s:%d]链接成功,newfd=%d\n",inet_ntoa(cin.sin_addr),\
ntohs(cin.sin_port),newfd);
pid=fork();
if(pid>0){
close(newfd);
}else if(pid==0){
close(sfd);
MY_sev(newfd,cin);
exit(EXIT_SUCCESS);
}else{
perror("fock error");
return -1;
}
}
close(sfd);
return 0;
}
2.多线程
#include "myhead.h"
#define PORT 2437
#define IP "192.168.125.115"
struct pthread_node{
int newfd;
struct sockaddr_in cin;
};
void *task(void *arg){
//5.收发数据
int newfd=((struct pthread_node*)arg)->newfd;
struct sockaddr_in cin=((struct pthread_node*)arg)->cin;
char rbuf[128]="";
while(1){
bzero(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);
strcat(rbuf,":)");
send(newfd,rbuf,sizeof(rbuf),0);
}
close(newfd);
pthread_exit(NULL);
}
int main(int argc, const char *argv[])
{
//1.创建套接字
int sfd=-1;
if((sfd=socket(AF_INET,SOCK_STREAM,0))==-1){
perror("socket error");
return -1;
}
printf("sfd=%d\n",sfd);
int reuse=1;
if(setsockopt(sfd,SOL_SOCKET,SO_REUSEADDR,&reuse,sizeof(reuse))==-1){
perror("setsockopt error");
return -1;
}
//2.绑定地址信息结构体
struct sockaddr_in sin;
sin.sin_family=AF_INET;
sin.sin_port=htons(PORT);
sin.sin_addr.s_addr=inet_addr(IP);
//2.1填充地址信息结构体
//2.2绑定工作
if(bind(sfd,(struct sockaddr*)&sin,sizeof(sin))==-1){
perror("bind error");
return -1;
}
printf("bind success_%d_%s_%s\n",__LINE__,__FILE__,__func__);
//3.将套接字设置成被动监听状态
if(listen(sfd,128)==-1){
perror("listen error");
return -1;
}
printf("listen success_%d_%s_%s\n",__LINE__,__FILE__,__func__);
//4.1定义用于接收客户端地址信息的结构体变量
struct sockaddr_in cin;
socklen_t socklen=sizeof(cin);
//4.2接收客户端链接请求
int newfd=-1;
pthread_t tid=-1;
while(1){
if((newfd=accept(sfd,(struct sockaddr*)&cin,&socklen))==-1){
perror("accept error");
return -1;
}
printf("[%s:%d]链接成功,newfd=%d\n",inet_ntoa(cin.sin_addr),\
ntohs(cin.sin_port),newfd);
struct pthread_node info={newfd,cin};
if((tid=pthread_create(&tid,NULL,task,&info))!=0){
perror("tid create error");
return -1;
}
pthread_detach(tid);
}
close(sfd);
return 0;
}