TCP并发服务器(多进程)
#define SER_IP "192.168.71.128"
#define SER_PORT 8888
void handler(int signo)
{
if(signo==SIGCHLD);
{
while(waitpid(-1,NULL,WNOHANG)>0); //循环回收僵尸进程
}
}
int main(int argc, const char *argv[])
{
//将signal和信号处理函数绑定
if(signal(SIGCHLD,handler)==SIG_ERR)
{
perror("signal");
return -1;
}
//创建一个套接字用于接受请求
int sfd=socket(AF_INET,SOCK_STREAM,0);
{
if(sfd==-1)
{
perror("socket");
return -1;
}
}
printf("socket success\n");
//设置快速端口重用
int reuse=-1;
if(setsockopt(sfd,SOL_SOCKET,SO_REUSEADDR,&reuse,sizeof(reuse))==-1)
{
perror("setsockopt");
return -1;
}
//设置结构体填充,并且绑定IP地址
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 socklen = sizeof(cin); //接受地址的长度
while(1) // 循环服务器
{
int newfd=accept(sfd,(struct sockaddr*)&cin,&socklen); //定义一个newfd用来接收数据
if(newfd==-1)
{
perror("accept");
return -1;
}
//建立子进程,用于通信
pid_t pid=fork();
if(pid>0)
{
close(newfd);
}else if(pid==0)
{
close(sfd);
char rbuf[128]="";
while(1)
{
bzero(rbuf,sizeof(rbuf));
//接受客户端发来的消息
int ret=recv(newfd,rbuf,sizeof(rbuf),0);
if(ret==0)
{
printf("客户端已下线\n");
break;
}
printf("[%s:%d];%s\n",\
inet_ntoa(cin.sin_addr),ntohs(cin.sin_port),rbuf);
//回复消息
strcat(rbuf,"*_*");
send(newfd,rbuf,strlen(rbuf),0);
printf("发送成功\n");
}
close(newfd);
//关闭子进程
exit(EXIT_SUCCESS);
}
}
close(sfd);
return 0;
}
TCP并发服务器(多线程)
#define SER_IP "192.168.71.128" //服务器IP地址
#define SER_PORT 8888 //服务器端口号
//定义一个传参的结构体
struct MsgInfo
{
int newfd;
struct sockaddr_in cin;
};
//定义分支线程函数部分
void *deal_cli_msg(void *arg)
{
//将传送的数据解析出来
int newfd = ((struct MsgInfo*)arg)->newfd;
struct sockaddr_in cin = ((struct MsgInfo*)arg)->cin;
//5、数据通信
char rbuf[128] = ""; //用于接受消息
while(1)
{
bzero(rbuf, sizeof(rbuf)); //清空容器
//从套接字文件中读取消息
//int ret = read(newfd, rbuf, sizeof(rbuf));
int ret = recv(newfd, rbuf, sizeof(rbuf), 0);
if(ret == 0)
{
printf("客户端已下线\n");
break;
}
printf("[%s:%d]: %s\n", \
inet_ntoa(cin.sin_addr), ntohs(cin.sin_port),rbuf );
//将字符串加个笑脸回回去
strcat(rbuf, "*_*");
//write(newfd, rbuf, strlen(rbuf));
send(newfd, rbuf, strlen(rbuf), 0);
printf("发送成功\n");
}
//6、关闭套接字
close(newfd);
//退出线程
pthread_exit(NULL);
}
/********主程序*********/
int main(int argc, const char *argv[])
{
//1、创建套节字:用于接收客户端链接请求的
int sfd = socket(AF_INET, SOCK_STREAM, 0);
if(sfd == -1)
{
perror("socket error");
return -1;
}
printf("socket success sfd = %d\n", sfd); //3
//设置端口号快速重用
int reuse = 1;
if(setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse))==-1)
{
perror("setsockopt error");
return -1;
}
printf("端口号快速重用成功\n");
//2、绑定IP地址和端口号
//2.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); //IP地址
//2.2 绑定工作
if( bind(sfd, (struct sockaddr*)&sin, sizeof(sin)) ==-1)
{
perror("bind error");
return -1;
}
printf("bind success\n");
//3、讲套节字设置成被动监听状态
if( listen(sfd, 128) == -1)
{
perror("listen error");
return -1;
}
printf("listen success\n");
//4、阻塞等待客户端连接请求
//定义地址信息结构体变量用于接受客户端的地址信息
struct sockaddr_in cin;
socklen_t socklen = sizeof(cin); //接受地址信息的长度
while(1)
{
int newfd = accept(sfd, (struct sockaddr*)&cin, &socklen);
if(newfd == -1)
{
perror("accept error");
return -1;
}
printf("[%s:%d]:已连接, newfd = %d\n",\
inet_ntoa(cin.sin_addr), ntohs(cin.sin_port) ,newfd); //4
//
struct MsgInfo info = {newfd,cin};
//创建分支线程
pthread_t tid=-1;
if(pthread_create(&tid,NULL,deal_cli_msg,&info)!=0)
{
printf("创建失败\n");
return -1;
}
// 回收分线程资源
pthread_detach(tid);
}
close(sfd);
return 0;
}
流套接字服务器
int main(int argc, const char *argv[])
{
//建立一个套接字 用于接受客户端请求
int sfd=socket(AF_UNIX,SOCK_STREAM,0);
if(sfd==-1)
{
perror("socket");
return -1;
}
printf("socket success sfd=%d\n",sfd);
//判断套接字文件是否存在,如果存在就删除
if(access("./unix",F_OK)==0)
{
if(unlink("./unix")!=0)
{
perror("accept");
return -1;
}
}
//定义一个结构体填充消息
struct sockaddr_un sun;
sun.sun_family=AF_UNIX;
strcpy(sun.sun_path,"./unix");
//绑定
if(bind(sfd,(struct sockaddr*)&sun,sizeof(sun))==-1)
{
perror("bind");
return -1;
}
printf("bind success\n");
//设置被动监听
if(listen(sfd,128)==-1)
{
perror("listen");
return -1;
}
printf("listen success\n");
//
struct sockaddr_un cun;
socklen_t socklen = sizeof(cun);
int newfd = accept(sfd,(struct sockaddr*)&cun,&socklen);
if(newfd==-1)
{
perror("newfd");
return -1;
}
printf("[%s]:已连接,newfd=%d\n",cun.sun_path,newfd);
//数据通信
char rbuf[128]="";
while(1)
{
bzero(rbuf,sizeof(rbuf));
int ret = read(newfd,rbuf,sizeof(rbuf));
if(ret==0)
{
printf("客户端已下线\n");
break;
}
printf("[%s]:%s\n",cun.sun_path,rbuf);
//将字符串加个笑脸回回去;
strcat(rbuf,"*_*");
send(newfd,rbuf,strlen(rbuf),0);
printf("发送成功\n");
}
//关闭套接字
close(sfd);
close(newfd);
return 0;
}
报式套接字服务器
{
//建立一个套接字 用于接受客户端请求
int sfd=socket(AF_UNIX,SOCK_STREAM,0);
if(sfd==-1)
{
perror("socket");
return -1;
}
printf("socket success sfd=%d\n",sfd);
//判断套接字文件是否存在,如果存在就删除
if(access("./unix",F_OK)==0)
{
if(unlink("./unix")!=0)
{
perror("accept");
return -1;
}
}
//定义一个结构体填充消息
struct sockaddr_un sun;
sun.sun_family=AF_UNIX;
strcpy(sun.sun_path,"./unix");
//绑定
if(bind(sfd,(struct sockaddr*)&sun,sizeof(sun))==-1)
{
perror("bind");
return -1;
}
printf("bind success\n");
//设置被动监听
if(listen(sfd,128)==-1)
{
perror("listen");
return -1;
}
printf("listen success\n");
//
struct sockaddr_un cun;
socklen_t socklen = sizeof(cun);
int newfd = accept(sfd,(struct sockaddr*)&cun,&socklen);
if(newfd==-1)
{
perror("newfd");
return -1;
}
printf("[%s]:已连接,newfd=%d\n",cun.sun_path,newfd);
//数据通信
char rbuf[128]="";
while(1)
{
bzero(rbuf,sizeof(rbuf));
int ret = read(newfd,rbuf,sizeof(rbuf));
if(ret==0)
{
printf("客户端已下线\n");
break;
}
printf("[%s]:%s\n",cun.sun_path,rbuf);
//将字符串加个笑脸回回去;
strcat(rbuf,"*_*");
send(newfd,rbuf,strlen(rbuf),0);
printf("发送成功\n");
}
//关闭套接字
close(sfd);
close(newfd);
return 0;
}