TCP并发服务器补充和UDP客户端和服务器

一 TCP并发服务器补充

用frok函数创建让子进程工作 

1服务器端

1 为了防止僵尸进程  要在栈区开辟空间  回收子进程 
2 用frok函数创建让子进程工作 
(kill 序号17 为回收信号)

在这里插入图片描述
在这里插入图片描述

#include<stdio.h>
#include<unistd.h>
#include<arpa/inet.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<string.h>
#include<stdlib.h>
#include<pthread.h>

void child(void *arg);//声明
void kill_wait(int num)
{
   if(num==SIGCHLD)
   {
   waitpid(-1,NULL,WNOHANG);
   }
}
int  main()
{
      int fd =-1;
      struct sockaddr_in  sin;
      
      fd=socket(AF_INET,sock_stream,0);
      kill_wait(SIGCHID);
      if(fd<0)
      {
         perror("socket");
        exit(1);
      }
      
      bzero(&sin,sizeof(sin));
      
      sin.sin_family=AF_INET;
      sin.sin_port=htons(5003);
    //  sin.sin_addr.s_addr=inet_addr("192.168.2129");
       sin.sin_addr.s_addr=INADDR_INY;
      if(bind(fd,(struct sockaddr *)&sin,sizeof(sin))<0)
     {
              perror("bind");
               exit(1);
     }
     
     if(listen(fd,5)<0)
     {
            perror("listen");
               exit(1);
     }
     
     int newfd=-1;
     char buf[1024];
     struct sockaddr_in cin;
     socklen len=sizeof(cin);
      pid_t pid;
   while(1)
   {
     newfd=accept(fd,(struct sockaddr* )&cin,&len);//&ci哪里都存有端口号和 i 地址了但是现在为网络字节序 需要转为主机字节序
    
     if(newfd<0)
     {
            perror("accept");
               exit(1);
     }
    char ipv4_buf[16];//比如 192.168.2.129+'/' ==14个字符   所以数组不要过多大这个大小
  if(!inet_ntop(AF_INET,(void *)&cin.sin_addr.s_addr,ipv4_buf,sizeof(cin)))
  {
          perror("inet_ntop");
               exit(1);
  }
   printf("IPV4=====%s port====%d\n",ipv4_buf,ntohs(cin.sin_port));
                      //ntohs函数网络字节序转为主机字节序
     pid=fork();

   if(pid<0)
   {
      break;
   }
   if(pid==0)
   {
     close(fd);
     child(&newfd);// 子进程工作 
  }
  if(pid>0)
   {
     close(newfd);
     
  }
}                              
   
     
         close(fd);
        close(newfd);
        return 0}


void child(void *arg)
{
        char buf[1024];
       int rts=-1;
       int newfd=*(int *)arg;
        while(1)
     {
        
         do
            {
           bzero(buf,1024);
           rts=read(newfd,buf,1023);
            
         }while(rts<1);//while(rts<1);==rts>1
    
         if(rts<0)
         {
             exit(1);
         }
           if(rts==0)
         {
              break;
        }
         printf("read is %s\n",buf);
    
     }
          close(fd);
        close(newfd);
}     


二 客户端

#include<stdio.h>
#include<unistd.h>
#include<arpa/inet.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<string.h>
#include<stdlib.h>

int  main(int argc,char **argv)
{
      int fd =-1;
      struct sockaddr_in  sin;
      if(argc!=3)
      {
       exit(1);
      }
      int port =atoi(argv[2]);
      //XXXX  192.186.2.129 5003
      fd=socket(AF_INET,sock_stream,0);
     
      if(fd<0)
      {
         perror("socket");
        exit(1);
      }
      
      bzero(&sin,sizeof(sin));
      
      sin.sin_family=AF_INET;
      sin.sin_port=htons(port);
      sin.sin_addr.s_addr=inet_addr(argv[1]);
      //XXXX  192.186.2.129 5003 
     if(connect(fd,(struct sockaddr*)&sin,sizeof(sin))<0)
     {
           perror("connect");
            exit(1);
     }
     char buf[1024];
     while(1)
     {
            bzero(buf,1024);
            if(fgets(buf,1023,stdin)==NULL)
            {
            continue}
            
            write(fd,buf,sizeof(buf))}


     return 0;
}


在这里插入图片描述

UDP客户端和服务器

在这里插入图片描述

基本流程都一样 
UDP 是不可靠传输 不用 listen函数主动转为被动  不用accept 阻塞等待
因为他的发送不需要考虑缓存问题  只管发送  不考虑 接收的问题
服务器:修改对应的套接字类型 
因为不需要考虑缓存问题 所以 要重映射函数 不断换输出位置 
读取函数也有所修改 不过差别不大

在这里插入图片描述

服务器
recvfrom函数

先 知道recvfrom函数 用法 上面有链接
#include<stdio.h>
#include<unistd.h>
#include<arpa/inet.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<string.h>
#include<stdlib.h>
#include<pthread.h>
#include<strings.h>




int  main()
{
      int fd =-1;
      struct sockaddr_in  sin;

      fd=socket(AF_INET,SOCK_DGRAM,0);
     
      if(fd<0)
      {
         perror("socket");
        exit(1);
      }
      int ys=-1;
    // 重映射 
     setsockopt(fd,SOL_SOCKET,SO_REUSEADR,&ys,sizeof(int));//先用 别纠结 
        
    
      bzero(&sin,sizeof(sin));

      sin.sin_family=AF_INET;
      sin.sin_port=htons(6000);
    //  sin.sin_addr.s_addr=inet_addr("192.168.2129");
       sin.sin_addr.s_addr=INADDR_INY;
    
     int newfd=-1;
     char buf[1024];
     struct sockaddr_in cin;
     socklen len=sizeof(cin);
 
     while(1)
   {
        bzero(buf,1024);  
      if(recvfrom(fd,buf,1023,0,(struct sockaddr *)&cin,&len)<0)
      {
         perror("recvfrom");
          continue;//没数据 就退出一次 
      }
   
   
    char ipv4_buf[16];//比如 192.168.2.129+'/' ==14个字符   所以数组不要过多大这个大小
  if(!inet_ntop(AF_INET,(void *)&cin.sin_addr.s_addr,ipv4_buf,sizeof(cin)))
  {
          perror("inet_ntop");
               exit(1);
  }
   printf("IPV4=====%s port====%d data is %s\n",ipv4_buf,ntohs(cin.sin_port),buf);
                      //ntohs函数网络字节序转为主机字节序
  
}
         close(fd);
        close(newfd);
        return 0}

客户端
sendto函数

先 知道send 函数 用法 上面有链接
#include<stdio.h>
#include<unistd.h>
#include<arpa/inet.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<string.h>
#include<stdlib.h>

int  main(int argc,char **argv)
{
      int fd =-1;
      struct sockaddr_in  sin;
      if(argc!=3)
      {
       exit(1);
      }
      int port =atoi(argv[2]);
      //XXXX  192.186.2.129 5003
      fd=socket(AF_INET,SOCK_DGRAM,0);
     
      if(fd<0)
      {
         perror("socket");
        exit(1);
      }
      
      bzero(&sin,sizeof(sin));
      
      sin.sin_family=AF_INET;
      sin.sin_port=htons(port);
      sin.sin_addr.s_addr=inet_addr(argv[1]);
      //XXXX  192.186.2.129 5003 
  
     char buf[1024];
     while(1)
     {
            bzero(buf,1024);
            if(fgets(buf,1023,stdin)==NULL)
            {
            continue}
            
          sendto(fd,buf,1024,(struct sockaddr *)&sin,sizeof(sin));
            
    }


     return 0;
}


在这里插入图片描述

可以实现 验证成功 
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值