2024/4/24作业

1.广播模型

发送端

  1 #include<stdio.h>
  2 #include<sys/types.h>
  3 #include<sys/socket.h>
  4 #include<arpa/inet.h>
  5 #include<netinet/in.h>
  6 #include<string.h>
  7 #include<unistd.h>
  8 
  9 #define SER_PORT 8888
 10 #define SER_IP  "192.168.124.255"
 11 
 12 int main(int argc, const char *argv[])
 13 {
 14   //创建报式套接字
 15   int cfd=socket(AF_INET,SOCK_DGRAM,0);
 16   if(cfd<0)
 17   {
 18     fprintf(stderr,"line:%d ",__LINE__);
 19     perror("socket");
 20     return -1;
 21   }
 22   printf("创建报式套接字成功 cfd=%d __%d__\n",cfd,__LINE__);
 23 
 24   //设置允许广播
 25   int b=1;
 26   if(setsockopt(cfd,SOL_SOCKET,SO_BROADCAST,&b,sizeof(b))<0)
 27    {
 28    fprintf(stderr,"line:%d ",__LINE__);
 29    perror("setsockopt");
 30    return -1;
 31    }
 32 
 33 
 34   //填充服务器的地址信息结构体,给sendto函数使用
 35   //指定要将数据包发送给谁
 36   //AF_INET--->MAN 7 ip
 37   struct sockaddr_in sin;
 38   sin.sin_family   =AF_INET;//必须填AF_INET
 39   sin.sin_port     =htons(SER_PORT);//服务器绑定的端口号
 40   sin.sin_addr.s_addr=inet_addr(SER_IP);//服务器绑定的IP
 41 
 42   char buf[128]="";
 43   struct sockaddr_in rcvaddr;
 44   socklen_t addrlen=sizeof(rcvaddr);
 45   while(1)
 46    {
 47     bzero(buf,sizeof(buf));
 48     //发送
 49     printf("请输入>>>");
 50     fgets(buf,sizeof(buf),stdin);
 51     buf[strlen(buf)-1]=0;
 52     //将数据发送给接受方
 53     if(sendto(cfd,buf,sizeof(buf),0,(struct sockaddr*)&sin,sizeof(sin))<0)
 54     {
 55      fprintf(stderr,"line:%d ",__LINE__);
 56      perror("sendto");
 57      return -1;
 58     }
 59     printf("发送成功\n");
 60 
 61   }
 62    //关闭
 63   close(cfd);
 64    return 0;
 65 }
 66                                                                                

接收端

  1 #include<stdio.h>
  2 #include<sys/types.h>
  3 #include<sys/socket.h>
  4 #include<arpa/inet.h>
  5 #include<netinet/in.h>
  6 #include<string.h>
  7 #include<unistd.h>
  8 
  9 #define PORT 8888
 10 #define IP "192.168.124.255"
 11 
 12 int main(int argc, const char *argv[])
 13 {
 14    //创建报式套接字
 15    int sfd=socket(AF_INET,SOCK_DGRAM,0);
 16    if(sfd<0)
 17    {
 18      fprintf(stderr,"line:%d ",__LINE__);
 19      perror("socket");
 20      return -1;
 21    }
 22    printf("创建报式套接字成功 sfd=%d __%d__\n",sfd,__LINE__);
 23 
 24    //允许端口号被快速重复使用
 25    int reuse = 1;
 26    if(setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)) < 0)
 27      {
 28       fprintf(stderr, "line:%d  ", __LINE__);
 29       perror("setsockopt");
 30       return -1;
 31      }
 32 
 33    //填充服务器的地址信息结构体,真实的地址信息结构体根据地址族制定
 34    //AF_INET--->MAN 7 ip
 35    struct sockaddr_in sin;
 36    sin.sin_family   =AF_INET;//必须填AF_INET
 37    sin.sin_port     =htons(PORT);//端口号的网络字节序 1024~49151
 38    sin.sin_addr.s_addr=inet_addr(IP);//服务器要运行的主机的IP的网络地址
 39    //ifconfig查找本机的IP地址
 40    //绑定服务器自身的地址信息-->必须绑定
 41    if(bind(sfd,(struct sockaddr*)&sin,sizeof(sin))<0)
 42    {
 43      fprintf(stderr,"line:%d ",__LINE__);
 44      perror("bind");
 45      return -1;
 46    }
 47    printf("bind success __%d__\n",__LINE__);
 48 
 49    char buf[128]="";
 50    struct sockaddr_in cin;
 51    socklen_t addrlen=sizeof(cin);
 52    while(1)
 53    {
 54      bzero(buf,sizeof(buf));
 55      //接收
 56      //if(recvfrom(sfd,buf,sizeof(buf),0,NULL,NULL)<0)
 57      //if(recv(sfd,buf,sizeof(buf),0)<0)
 58      //if(read(sfd,buf,sizeof(buf))<0)
 59      if(recvfrom(sfd,buf,sizeof(buf),0,(struct sockaddr*)&cin,&addrlen)<0)
 60      {
 61        fprintf(stderr,"line:%d ",__LINE__);
 62        perror("recvfrom");
 63        return -1;
 64      }
 65      printf(":%s __%d__\n",buf,__LINE__);
 66    }
 67    close(sfd);
 68 
 69 
 70     return 0;
 71 }

2.组播模型

发送端

  1 #include<stdio.h>
  2 #include<sys/types.h>
  3 #include<sys/socket.h>
  4 #include<arpa/inet.h>
  5 #include<netinet/in.h>
  6 #include<string.h>
  7 #include<unistd.h>
  8 
  9 #define SER_PORT 8888
 10 #define GRP_IP  "224.1.2.3"
 11 
 12 int main(int argc, const char *argv[])
 13 {
 14   //创建报式套接字
 15   int cfd=socket(AF_INET,SOCK_DGRAM,0);
 16   if(cfd<0)
 17   {
 18     fprintf(stderr,"line:%d ",__LINE__);
 19     perror("socket");
 20     return -1;
 21   }
 22   printf("创建报式套接字成功 cfd=%d __%d__\n",cfd,__LINE__);
 23 
 24   //填充接收方的地址信息结构体,给sendto函数使用
 25   //指定要将数据包发送给谁
 26   //AF_INET--->MAN 7 ip
 27   struct sockaddr_in sin;
 28   sin.sin_family   =AF_INET;//必须填AF_INET
 29   sin.sin_port     =htons(SER_PORT);//服务器绑定的端口号
 30   sin.sin_addr.s_addr=inet_addr(GRP_IP);//服务器绑定的IP
 31 
 32   char buf[128]="";
 33   struct sockaddr_in rcvaddr;
 34   socklen_t addrlen=sizeof(rcvaddr);
 35   while(1)
 36    {
 37     bzero(buf,sizeof(buf));
 38     //发送
 39     printf("请输入>>>");
 40     fgets(buf,sizeof(buf),stdin);
 41     buf[strlen(buf)-1]=0;
 42     //将数据发送给接受方
 43     if(sendto(cfd,buf,sizeof(buf),0,(struct sockaddr*)&sin,sizeof(sin))<0)
 44     {
 45      fprintf(stderr,"line:%d ",__LINE__);
 46      perror("sendto");
 47      return -1;
 48     }
 49     printf("发送成功\n");
 50 
 51   }
 52    //关闭
 53   close(cfd);
 54    return 0;
 55 }
 56 

接收端

  1 #include<stdio.h>
  2 #include<sys/types.h>
  3 #include<sys/socket.h>
  4 #include<arpa/inet.h>
  5 #include<netinet/in.h>
  6 #include<string.h>
  7 #include<unistd.h>
  8 
  9 #define PORT 8888
 10 #define IP "192.168.124.93"
 11 #define GRP_IP "224.1.2.3"
 12 
 13 int main(int argc, const char *argv[])
 14 {
 15    //创建报式套接字
 16    int sfd=socket(AF_INET,SOCK_DGRAM,0);
 17    if(sfd<0)
 18    {
 19      fprintf(stderr,"line:%d ",__LINE__);
 20      perror("socket");
 21      return -1;
 22    }
 23    printf("创建报式套接字成功 sfd=%d __%d__\n",sfd,__LINE__);
 24 
 25    //加入多播组
 26    struct ip_mreqn mq;
 27    mq.imr_multiaddr.s_addr =inet_addr(GRP_IP);
 28    mq.imr_address.s_addr  =inet_addr(IP);
 29    mq.imr_ifindex =0;
 30    if(setsockopt(sfd,IPPROTO_IP,IP_ADD_MEMBERSHIP,&mq,sizeof(mq))<0)
 31    {
 32     fprintf(stderr,"line:%d ",__LINE__);
 33     perror("setsockopt");
 34     return -1;
 35    }
 36    printf("加入小组[%s]成功\n",GRP_IP);
 37    //允许端口号被快速重复使用
 38    int reuse = 1;
 39    if(setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)) < 0)
 40 
 41      {
 42       fprintf(stderr, "line:%d  ", __LINE__);
 43       perror("setsockopt");
 44       return -1;
 45      }
 46 
 47    //填充接收方的地址信息结构体,真实的地址信息结构体根据地址族制定
 48    //AF_INET--->MAN 7 ip
 49    struct sockaddr_in sin;
 50    sin.sin_family   =AF_INET;//必须填AF_INET
 51    sin.sin_port     =htons(PORT);//端口号的网络字节序 1024~49151
 52    sin.sin_addr.s_addr=inet_addr(GRP_IP);//接收方加入的组播IP
 53 
 54    //ifconfig查找本机的IP地址
 55    //绑定接收方自身的地址信息-->必须绑定
 56    if(bind(sfd,(struct sockaddr*)&sin,sizeof(sin))<0)
 57    {
 58      fprintf(stderr,"line:%d ",__LINE__);
 59      perror("bind");
 60      return -1;
 61    }
 62    printf("bind success __%d__\n",__LINE__);
 63 
 64    char buf[128]="";
 65    struct sockaddr_in cin;
 66    socklen_t addrlen=sizeof(cin);
 67    while(1)
 68    {
 69      bzero(buf,sizeof(buf));
 70      //接收
 71      //if(recvfrom(sfd,buf,sizeof(buf),0,NULL,NULL)<0)
 72      //if(recv(sfd,buf,sizeof(buf),0)<0)
 73      //if(read(sfd,buf,sizeof(buf))<0)
 74      if(recvfrom(sfd,buf,sizeof(buf),0,(struct sockaddr*)&cin,&addrlen)<0)
 75      {
 76        fprintf(stderr,"line:%d ",__LINE__);
 77        perror("recvfrom");
 78        return -1;
 79      }
 80      printf(":%s __%d__\n",buf,__LINE__);
 81    }
 82    close(sfd);
 83 
 84    
 85     return 0;
 86 }

3.TCP进程并发模型

  1 #include<stdio.h>
  2 #include<sys/types.h>
  3 #include<sys/socket.h>
  4 #include<arpa/inet.h>
  5 #include<netinet/in.h>
  6 #include<string.h>
  7 #include<unistd.h>
  8 #include<stdlib.h>
  9 #include<sys/wait.h>
 10 #include<signal.h>
 11 
 12 #define PORT 8888
 13 #define IP "192.168.124.93"
 14 
 15 int do_cli_msg(int newfd,struct sockaddr_in cin);
 16 
 17 void recycle_zombie(int sig)
 18 {
 19  while(waitpid(-1,NULL,WNOHANG)>0);
 20  return;
 21 }
 22 
 23 int main(int argc, const char *argv[])
 24 {
 25     //捕获17)SIGCHLD信号
 26     if(signal(SIGCHLD,recycle_zombie)==SIG_ERR)
 27     {
 28      perror("signal");
 29      return -1;
 30     }
 31     //创建流式套接字文件
 32     int sfd=socket(AF_INET,SOCK_STREAM,0);
 33     if(sfd<0)
 34     {
 35         fprintf(stderr,"line:%d  \n",__LINE__);
 36         perror("socket");
 37         return -1;
 38     }
 39     printf("创建流式套接字成功 sfd=%d    __%d__\n",sfd,__LINE__);
 40 
 41     //允许端口号被快速重复使用
 42     int reuse = 1;
 43     if(setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)) < 0)
 44     {
 45         fprintf(stderr, "line:%d  ", __LINE__);
 46         perror("setsockopt");
 47         return -1;
 48     }
 49 
 50     //填充服务器的地址信息结构体,真实的地址信息结构体根据地址族制定
 51     //AF_INET--->man 7 ip
 52     struct sockaddr_in  sin;
 53     sin.sin_family        =AF_INET;   //必须填AF_INET
 54     sin.sin_port          =htons(PORT);//端口号的网络字节序1024~49151
 55     sin.sin_addr.s_addr   =inet_addr(IP);//服务器要运行的主机的IP的网络地址
 56     //ifconfig查找本机的IP地址
 57     //绑定服务器自身的地址信息-->必修绑定
 58     if(bind(sfd,(struct sockaddr*)&sin,sizeof(sin))<0)
 59     {
 60         fprintf(stderr,"line:%d ",__LINE__);
 61         perror("bind");
 62         return -1;
 63     }
 64     printf("bind success __%d__\n",__LINE__);
 65 
 66     //将套接字设置为被动监听状态
 67     if(listen(sfd,128)<0)
 68     {
 69         fprintf(stderr,"line:%d ",__LINE__);
 70         perror("listen");
 71         return -1;
 72     }
 73     printf("listen success __%d__\n",__LINE__);
 74 
 75     struct sockaddr_in  cin;  //存储客户端信息的
 76     socklen_t addrlen=sizeof(cin);
 77     int newfd;
 78     pid_t pid=0;
 79 
 80     while(1)
 81     {
 82         //父进程只负责连接(accept)
 83         //会从已完成连接队列的对头获取一个客户端的信息,生成一个新的文件描述符
 84         //accept(sfd,NULL,NULL);
 85         newfd= accept(sfd,(struct sockaddr*)&cin,&addrlen);
 86         if(newfd<0)
 87         {
 88             fprintf(stderr,"line:%d ",__LINE__);
 89             perror("accept");
 90             return -1;
 91         }
 92         printf("[%s:%d] 客户端连接成功 newfd=%d  __%d__\n",inet_ntoa(cin.sin_addr),ntohs(cin.sin_port),newfd,__LINE__);
 93 
 94         //能运行到当前位置,则代表有客户端连接成功
 95         //此时需要创建一个新的进程,专门用于与客户端进行通信--->子进程只负责收发
 96         pid = fork();
 97         if(0==pid)
 98         {
 99             close(sfd); //sfd用于监听客户端连接,对于子进程没有用
100             do_cli_msg(newfd,cin);
101             close(newfd); //执行完交互后,newfd没有用了,需要关闭
102             exit(0);//子进程只负责收发,所以任务结束后,一定要退出子进程
103         }
104         else if(pid>0)
105         {
106             close(newfd);
107         }
108         else
109         {
110             fprintf(stderr,"line:%d ",__LINE__);
111             perror("fork");
112             return -1;
113         }
114     }
115     //关闭文件描述符
116     close(sfd);
117     return 0;
118 }
119 
120 
121 //子进程中用于处理于客户端交互的功能代码
122 int do_cli_msg(int newfd,struct sockaddr_in cin)
123 {
124     char buf[128];
125     ssize_t res;
126     while(1)
127     {
128         bzero(buf,sizeof(buf));
129         //接收
130         res=recv(newfd,buf,sizeof(buf),0);
131         if(res<0)
132         {
133             fprintf(stderr,"line:%d ",__LINE__);
134             perror("recv");
135             return -1;
136         }
137         else if(0==res)
138         {
139             printf("[%s:%d] 客户端下线 newfd=%d __%d__\n",inet_ntoa(cin.sin_addr),ntohs(cin.sin_port),newfd,__LINE__);
140             break;
141         }
142         printf("[%s:%d]  newfd=%d  %s __%d__\n",inet_ntoa(cin.sin_addr),ntohs(cin.sin_port),newfd,buf,__LINE__);
143 
144         //发送
145         strcat(buf,"*_*");                                                                                                            
146         if(send(newfd,buf,sizeof(buf),0)<0)
147         {
148             fprintf(stderr,"line:%d ",__LINE__);
149             perror("send");
150             return -1;
151         }
152         printf("send success __%d__\n",__LINE__);
153     }
154     return 0;
155 }                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      

4.TCP线程并发模型 

  1 #include<stdio.h>
  2 #include<sys/types.h>
  3 #include<sys/socket.h>
  4 #include<arpa/inet.h>
  5 #include<netinet/in.h>
  6 #include<string.h>
  7 #include<unistd.h>
  8 #include<stdlib.h>
  9 #include<sys/wait.h>
 10 #include<signal.h>
 11 #include<pthread.h>
 12 
 13 #define PORT 8888
 14 #define IP "192.168.124.93"
 15 
 16 //传入到分支线程回调函数的参数类型
 17 struct CliInfo
 18 {
 19    int newfd;
 20    struct sockaddr_in cin;
 21 };
 22 void* do_cli_msg(void* arg);
 23 
 24 int main(int argc, const char *argv[])
 25 {
 26     //创建流式套接字文件
 27     int sfd=socket(AF_INET,SOCK_STREAM,0);
 28     if(sfd<0)
 29     {
 30         fprintf(stderr,"line:%d  \n",__LINE__);
 31         perror("socket");
 32         return -1;
 33     }
 34     printf("创建流式套接字成功 sfd=%d    __%d__\n",sfd,__LINE__);
 35 
 36     //允许端口号被快速重复使用
 37     int reuse = 1;
 38     if(setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)) < 0)
 39     {
 40         fprintf(stderr, "line:%d  ", __LINE__);
 41         perror("setsockopt");
 42         return -1;
 43     }
 44 
 45     //填充服务器的地址信息结构体,真实的地址信息结构体根据地址族制定
 46     //AF_INET--->man 7 ip
 47     struct sockaddr_in  sin;
 48     sin.sin_family        =AF_INET;   //必须填AF_INET
 49     sin.sin_port          =htons(PORT);//端口号的网络字节序1024~49151
 50     sin.sin_addr.s_addr   =inet_addr(IP);//服务器要运行的主机的IP的网络地址
 51     //ifconfig查找本机的IP地址
 52     //绑定服务器自身的地址信息-->必修绑定
 53     if(bind(sfd,(struct sockaddr*)&sin,sizeof(sin))<0)
 54     {
 55         fprintf(stderr,"line:%d ",__LINE__);
 56         perror("bind");
 57         return -1;
 58     }
 59     printf("bind success __%d__\n",__LINE__);
 60 
 61     //将套接字设置为被动监听状态
 62     if(listen(sfd,128)<0)
 63     {
 64         fprintf(stderr,"line:%d ",__LINE__);
 65         perror("listen");
 66         return -1;
 67     }
 68     printf("listen success __%d__\n",__LINE__);
 69 
 70     struct sockaddr_in  cin;  //存储客户端信息的
 71     socklen_t addrlen=sizeof(cin);
 72     int newfd;
 73     pthread_t tid;
 74     struct CliInfo dcli;
 75 
 76     while(1)
 77     {
 78         //主线程只负责连接(accept)
 79         //会从已完成连接队列的对头获取一个客户端的信息,生成一个新的文件描述符
 80         //当代码阻塞在accept函数的位置时,会遍历文件文件描述符找到最小的没有被使用的文件描述符,并占用
 81         //accept(sfd,NULL,NULL);
 82         newfd= accept(sfd,(struct sockaddr*)&cin,&addrlen);
 83         if(newfd<0)
 84         {
 85             fprintf(stderr,"line:%d ",__LINE__);
 86             perror("accept");
 87             return -1;
 88         }
 89         printf("[%s:%d] 客户端连接成功 newfd=%d  __%d__\n",inet_ntoa(cin.sin_addr),ntohs(cin.sin_port),newfd,__LINE__);
 90 
 91         //能运行到当前位置,则代表有客户端连接成功,此时需要创建一个分支线程负责交互
 92         //分支线程只负责交互
 93         dcli.newfd=newfd;
 94         dcli.cin=cin;
 95         if(pthread_create(&tid,NULL,do_cli_msg,(void*)&dcli)!=0)
 96         {
 97           fprintf(stderr,"line:%d  pthread_create failed\n",__LINE__);
 98           return -1;
 99         }
100         pthread_detach(tid);   //分离线程,tid线程退出后资源自动被回收
101         }
102         //关闭文件描述符
103     close(sfd);
104     return 0;
105 }
106 
107         //分支线程的回调函数
108 void* do_cli_msg(void* arg)  //void* arg=(void*)&dcli
109 {
110     int newfd=((struct CliInfo*)arg)->newfd;
111     struct sockaddr_in cin=((struct CliInfo*)arg)->cin;
112     char buf[128];
113     ssize_t res;
114     while(1)
115     {
116         bzero(buf,sizeof(buf));
117         //接收
118         res=recv(newfd,buf,sizeof(buf),0);
119         if(res<0)
120         {
121             fprintf(stderr,"line:%d ",__LINE__);
122             perror("recv");
123             break;
124         }
125         else if(0==res)
126         {
127             printf("[%s:%d] 客户端下线 newfd=%d __%d__\n",inet_ntoa(cin.sin_addr),ntohs(cin.sin_port),newfd,__LINE__);
128             break;
129         }
130         printf("[%s:%d]  newfd=%d  %s __%d__\n",inet_ntoa(cin.sin_addr),ntohs(cin.sin_port),newfd,buf,__LINE__);
131 
132         //发送
133         strcat(buf,"*_*");
134         if(send(newfd,buf,sizeof(buf),0)<0)
135         {
136             fprintf(stderr,"line:%d ",__LINE__);
137             perror("send");
138             break;
139         }
140         printf("send success __%d__\n",__LINE__);
141     }
142      close(newfd);
143      pthread_exit(NULL);
144 }
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 

 

 

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值