多进程并发服务器
#include <myhead.h>
#define PORT 8888 //本机端口号
#define IP "192.168.114.57" //本机IP
void handler(int sig)
{
int res;
while(1)
{
res = waitpid(-1,NULL,WNOHANG);
if(res<0)
{
break;
}
}
}
int tcp_send(int newfd, struct sockaddr_in cin);
int main(int argc, const char *argv[])
{
//回收僵尸进程
if(signal(17,handler) == SIG_ERR)
{
ERR_MSG(signal error);
return -1;
}
//创建流式套接字文件
int sfd;
if((sfd = socket(AF_INET,SOCK_STREAM,0))<0)
{
ERR_MSG("socket error");
return -1;
}
//端口复用
int use =1;
if(setsockopt(sfd,SOL_SOCKET,SO_REUSEADDR,&use,sizeof(use))<0)
{
ERR_MSG("set error");
return -1;
}
//填充服务器的端口号和IP地址给bind函数使用
struct sockaddr_in sin;
sin.sin_family = AF_INET;
sin.sin_port = htons(PORT);
sin.sin_addr.s_addr = inet_addr(IP);
//绑定服务器的端口号和IP地址
if(bind(sfd,(struct sockaddr *)&sin,sizeof(sin))<0)
{
ERR_MSG("bind error");
return -1;
}
printf("bind success\n");
//将sfd套接字设置为被动监听状态
if(listen(sfd,128)<0)
{
ERR_MSG("listen error");
return -1;
}
printf("listen success\n");
struct sockaddr_in cin;
int len = sizeof(cin);
int newfd;
while(1)
{
//接收请求
if((newfd = accept(sfd,(struct sockaddr *)&cin,&len))<0)
{
ERR_MSG("accept error");
return -1;
}
printf("accept success newfd =%d\n",newfd);
pid_t pid;
pid = fork();
if(pid ==0)
{
//子进程控制收发
close(sfd);
//调用收发函数
tcp_send(newfd,cin);
close(newfd);
exit(0);
}
close(newfd);
}
close(sfd);
return 0;
}
int tcp_send(int newfd, struct sockaddr_in cin)
{
//定义一个搬运工
char buf[128]= "";
int ret = 0;
while(1)
{
bzero(buf,sizeof(buf));
//recv函数使用
ret = recv(newfd,buf,sizeof(buf),0);
if(ret<0)
{
break;
}
else if(ret == 0)
{
printf("客户端下线 newfd = %d\n",newfd);
break;
}
printf("%s\n",buf);
/* //发送函数
bzero(buf,sizeof(buf));
printf("请输入>>>");
//从终端获取字符串
fgets(buf,sizeof(buf),stdin);
//将'\n'替换'\0'
buf[strlen(buf)-1] == '\0';
if(send(newfd,buf,sizeof(buf),0)<0)
{
ERR_MSG("send error");
return -1;
}
printf("send success %d\n",newfd); */
}
//关闭文件
close(newfd);
}
多线程并发服务器
#include <myhead.h>
#define PORT 8888
#define IP "192.168.114.57"
void *task(void *arg);
struct msg
{
int newfd;
struct sockaddr_in cin;
};
int main(int argc, const char *argv[])
{
//创建流式套接字
int sfd;
if((sfd = socket(AF_INET,SOCK_STREAM,0))<0)
{
ERR_MSG("socket error");
return -1;
}
printf("socket success sfd =%d\n",sfd);
//允许端口复用
int use =1;
if(setsockopt(sfd,SOL_SOCKET,SO_REUSEPORT,&use,sizeof(use))<0)
{
ERR_MSG("set error");
return -1;
}
//填充端口和IP地址结构体给bind函数使用
struct sockaddr_in sin;
sin.sin_family =AF_INET;
sin.sin_port =htons(PORT);
sin.sin_addr.s_addr =inet_addr(IP);
//绑定服务器端口和IP
if(bind(sfd,(struct sockaddr *)&sin,sizeof(sin))<0)
{
ERR_MSG(bind error);
return -1;
}
printf("%d\n",sfd);
printf("bind success\n");
//将sfd设置为被动监听状态
if(listen(sfd,128)<0)
{
ERR_MSG(listen);
return -1;
}
printf("listen success\n");
struct sockaddr_in cin;
int len = sizeof(cin);
int newfd;
//定义一个子线程
pthread_t tid;
struct msg info;
while(1)
{
//获取连接成功后的套接字
if(newfd = accept(sfd,(struct sockaddr *)&cin,&len)<0)
{
ERR_MSG("accept error");
return -1;
}
printf("accept success,newfd = %d\n",newfd);
info.newfd =newfd;
info.cin =cin;
//创建子线程
if(pthread_create(&tid,NULL,task,(void *)&info)<0)
{
printf("create error");
return -1;
}
//分离
pthread_detach(tid);
}
close(sfd);
return 0;
}
void *task(void *arg)
{
int newfd = ((struct msg*)arg)->newfd;
struct sockaddr_in cin =((struct msg *)arg)->cin;
int ret=0;
char buf[128];
while(1)
{
//接收
bzero(buf,sizeof(buf));
ret = recv(newfd,buf,sizeof(buf),0);
if(ret <0)
{
ERR_MSG("recv error");
break;
}
else if(ret ==0)
{
printf("客户端下线 newfd = %d\n",newfd);
}
printf("%s",buf);
//发送
bzero(buf,sizeof(buf));
//从终端输入字符串
fgets(buf,sizeof(buf),stdin);
buf[strlen(buf)-1] =='\0';
if(send(newfd,buf,sizeof(buf),0)<0)
{
ERR_MSG("send error");
break;
}
}
close(newfd);
pthread_exit(NULL);
}
文章介绍了使用C语言实现的多进程和多线程并发服务器,包括创建套接字、端口复用、绑定、监听和处理客户端连接的步骤。
1444

被折叠的 条评论
为什么被折叠?



