完成并发服务器搭建

//多进程并发
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<unistd.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<pthread.h>
#define ERR_MSG(msg)do{\
	fprintf(stderr,"line%d\n",__LINE__);\
	perror(msg);\
}while(0)
#define IP "192.168.31.107"
#define PORT 2324
struct cli_msg
{
int newfd;
struct sockaddr_in cin;
};
void* deal_cli_amsg(void* arg);

int main(int argc, const char *argv[])
{
	//创建流式套接字
   int sfd=socket(AF_INET,SOCK_STREAM,0);
   if(sfd<0)
   {
   ERR_MSG("socket");
   return -1;
   }
    //端口快速启用
	 int reuse=1;
	 if(setsockopt(sfd,SOL_SOCKET,SO_REUSEADDR,&reuse,sizeof(reuse))<0)
	 {
	 ERR_MSG("setsockopt");
	 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))<0)
	  {
	  ERR_MSG("bind");
	  return -1;
	  }
       printf("bind success%d\n",__LINE__);
	   //监听状态
	    if(listen(sfd,128)<0)
		{
		ERR_MSG("listen");
		return -1;
		}
      printf("listen success %d\n",__LINE__);
	  //存储连接成功的客户端地址信息
	   struct sockaddr_in cin;
	   socklen_t addrlen=sizeof(cin);
	   int newfd=-1;
	   pthread_t tid;
	   struct cli_msg info;
	   //连接
	    while(1)
		{
			newfd=accept(sfd,(struct sockaddr*)&cin,&addrlen);
		
			if(newfd<0)
			{
				ERR_MSG("accept");
				return -1;
			}
			printf("[%s:%d]newfd %d 连接成功__%d__\n",inet_ntoa(cin.sin_addr),ntohs(cin.sin_port),newfd,__LINE__);
			info.newfd=newfd;
			info.cin=cin;
			//分支线程,用来与客户端交互使用
			if ( pthread_create(&tid,NULL,(void *)deal_cli_amsg,(void *)&info)!=0)
			{
				ERR_MSG("pthread_create");
				return -1;

			}
			pthread_detach(tid);
		}
		close(sfd);
		return 0;
}
void* deal_cli_amsg(void* arg)
{
 int newfd=(*(struct cli_msg*)arg).newfd;
 struct sockaddr_in cin =(*(struct cli_msg*)arg).cin;
 char buf[128]="";
 ssize_t res=0;
 while(1)
 {
 bzero(buf,sizeof(buf));
 //接收
  res=recv(newfd,buf,sizeof(buf),0);
  if(res<0)
  {
  ERR_MSG("recv");
  break;
  }else if(0==res)
  {
    printf("[%s %d]newfd=%d客户端下线%d\n",inet_ntoa(cin.sin_addr),ntohs(cin.sin_port),newfd,__LINE__);
	break;
  }
   printf("[%s:%d]newfd:%d:%s %d\n",inet_ntoa(cin.sin_addr),ntohs(cin.sin_port),newfd,buf,__LINE__);
   //发送
    strcat(buf,"_*_");
    if(send(newfd,buf,sizeof(buf),0)<0)
	{
	ERR_MSG("send");
	 break;
	}
	printf("发送成功\n");
  }
  close(newfd);
  pthread_exit(NULL);
 }

//多线程并发

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<unistd.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<signal.h>
#include<sys/wait.h>

#define ERR_MSG(msg)do{\
	fprintf(stderr,"line%d\n",__LINE__);\
	perror(msg);\
}while(0)
#define IP "192.168.31.107"
#define PORT 2324
int deal_cli_msg(int newfd,struct sockaddr_in cin);


	//回收僵尸进程
void handler(int sig)
{
	while(waitpid(-1,NULL,WNOHANG)>0);
}

int main(int argc, const char *argv[])
{
	__sighandler_t s=signal(SIGCHLD,handler);
	if(SIG_ERR==s)
	{
		ERR_MSG("signal");
		return -1;
	}
	//创建套接字
	int sfd=socket(AF_INET,SOCK_STREAM,0);
	if(sfd<0)
	{
		ERR_MSG("socket");
		return -1;
	}
	//端口快速重用
	int reuse=1;
	if(setsockopt(sfd,SOL_SOCKET,SO_REUSEADDR,&reuse,sizeof(reuse))<0)
	{
		ERR_MSG("setsockopt");
		return -1;
	}
	printf("端口快速重用\n");
	//填充服务器的地址信息结构体
	struct sockaddr_in sin;
	sin.sin_family=AF_INET;
	sin.sin_port=htons(PORT);
	sin.sin_addr.s_addr=inet_addr(IP);
	//bind绑定
	if(bind(sfd,(struct sockaddr*)&sin,sizeof(sin))<0)
	{
		ERR_MSG("bind");
		return -1;
	}
	printf("bind success %d\n",__LINE__);
	//listen监听状态
	if(listen(sfd,128)<0)
	{
		ERR_MSG("listen");
		return -1;
	}
	printf("listen success%d\n",__LINE__);
	//存储客户端的地址信息
	struct sockaddr_in cin;
	socklen_t addrlen=sizeof(cin);
	int newfd=-1;
	pid_t cpid =-1;
	while(1)
	{
		//获取
		newfd=accept(sfd,(struct sockaddr *)&cin,&addrlen);
		if(newfd<0)
		{
			ERR_MSG("accept");
			return -1;
		}
	printf("[%s :%d]newfd=%d__%d__\n",inet_ntoa(cin.sin_addr),ntohs(cin.sin_port),newfd,__LINE__);		//创建子进程
		cpid=fork();
		if(cpid>0)
		{
			close(newfd); //对父进程而言,newfd没有用
		}else if(0==cpid)
		{
			close(sfd);
			deal_cli_msg(newfd,cin);
		    close(newfd);	
	          exit(0);
	     }else
		 {
		 ERR_MSG("fork");
		 return -1;
		 }
	   close(newfd);
	}
	close(sfd);
	return 0;
}

int deal_cli_msg(int newfd,struct sockaddr_in cin)
{
	char buf[128]="";
	ssize_t res =0;
	while(1)
	{
		//清空
		bzero(buf,sizeof(buf));
		//接收
		res=recv(newfd,buf,sizeof(buf),0);
		if(res<0)
		{
			ERR_MSG("recv");
			return -1;
		}else if(0==res)
		{
			printf("[%s:%d]newfd=%d 客户端下线__%d__\n",inet_ntoa(cin.sin_addr),ntohs(cin.sin_port),newfd,__LINE__);
			break;

		}
		printf("[%s:%d]newfd=%d %s__%d__\n",inet_ntoa(cin.sin_addr),ntohs(cin.sin_port),newfd,buf,__LINE__);
		//发送
		strcat(buf,"_*_");
		if(send(newfd,buf,sizeof(buf),0)<0)
		{
			ERR_MSG("send");
			return -1;
		}
		printf("发送成功\n");
	}
	return 0;

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值