24.1.18 DAY5

思维导图:

24.1.18 DAY5_第1张图片

模拟面试题:

1.怎么修改文件描述符发标志位?

答:用fcntl函数取下旧文件标识位,在此基础上加上O_NINBLOCK属性,然后设置回去

2.udp本地通信需要注意哪些方面?

答:如果没有绑定套接字文件,服务器无法对客户端发送信息,客户端可以对服务器发送信息。

3.基于udp的聊天室如何实现数据群发?

答:在服务器端创建链表,存储客户端的信息,当有信息需要发送时遍历链表,发送指定客户端的信息。

4.基于udp的聊天室如何实现数据群发?

答:使用多进程,多线程或IO多路复用,poll多路复用。

5.TCP连接时的三次握手机制?

答:需要连接服务器与客户端时,客户端向服务器发送连接请求;服务器收到后向客户端发送已收到连接请求,发起连接请求;客户端收到连接请求后给出应答。

作业:

1.

  1 #include
  2 #define SER_PORT  8888             //服务器端口号
  3 #define SER_IP "192.168.122.122"    //服务器ip地址
  4 #define CLI_PORT 6666                //客户端的端口号
  5 #define CLI_IP "192.168.122.144"       //客户端ip地址
  6 
  7 
  8 int main(int argc, const char *argv[])
  9 {
 10     //1、创建用于通信的套接字文件描述符
 11     int cfd = -1;
 12     cfd = socket(AF_INET, SOCK_STREAM, 0);
 13     if(cfd == -1)
 14     {
 15         perror("socket error");
 16         return -1;
 17     }
 18     printf("cfd = %d\n", cfd);            //3
 19 
 20     //2、绑定(可选)
 21     //2.1 填充地址信息结构体
 22     struct sockaddr_in cin;
 23     cin.sin_family = AF_INET;
 24     cin.sin_port = htons(CLI_PORT);
 25     cin.sin_addr.s_addr = inet_addr(CLI_IP);
 26     //2.2绑定
 27     if(bind(cfd, (struct sockaddr*)&cin, sizeof(cin)) == -1)
 28     {
 29         perror("bind error");
 30         return  -1;
 31     }
 32     printf("bind  success\n");
 33     
 34     //3、连接服务器
 35     //3.1 填充服务器地址信息结构体
 36     struct sockaddr_in sin;
 37     sin.sin_family =     AF_INET;
 38     sin.sin_port =         htons(SER_PORT);
 39     sin.sin_addr.s_addr = inet_addr(SER_IP);
 40     //3.2 连接
 41     if(connect(cfd, (struct sockaddr*)&sin, sizeof(sin)) == -1)
 42     {
 43         perror("connect error");
 44         return -1;
 45     }
 46     printf("connect success\n");
 47     
 48     fd_set readfds;
 49     FD_ZERO(&readfds);
 50     FD_SET(0,&readfds);
 51     FD_SET(cfd,&readfds);
 52 
 53     //4、收发数据
 54     char buf[128] = "";
 55     while(1)
 56     {
 57         //清空数组
 58         bzero(buf, sizeof(buf));
 59 
 60         printf("请输入>>>");
 61         int res=select(cfd+1, &readfds, NULL, NULL, NULL);
 62         if(res==-1)
 63         {
 64             perror("select error");
 65             return -1;
 66         }
 67         else if(res==0)
 68         {
 69             printf("timeout\n");
 70             return -1;
 71         }
 72 
 73         fgets(buf, sizeof(buf), stdin);   //从终端输入数据
 74         buf[strlen(buf)-1] = 0;          //将换行改为'\0'
 75 
 76         //发送给服务器
 77         send(cfd, buf, sizeof(buf), 0);
 78 
 79         printf("发送成功\n");
 80         if(strcmp(buf, "quit") == 0)
 81         {
 82             break;
 83         }
 84 
 85         //接收服务器发来的消息
 86         recv(cfd, buf, sizeof(buf), 0);
 87         printf("[%s:%d]:%s\n", SER_IP, SER_PORT, buf);
 88     }
 89 
 90     //5、关闭套接字
 91     close(cfd);
 92 
 93     return 0;
 94 }
 95                                                                                                                                                                                                       
~                  

2.

  1 #include
  2 #define SER_PORT 8888                  //服务器端口号
  3 #define SER_IP  "192.168.122.144"      //服务器IP地址
  4 
  5 
  6 int main(int argc, const char *argv[])
  7 {
  8     //1、创建用于连接的套接字
  9     int sfd = socket(AF_INET, SOCK_STREAM, 0);
 10     //参数1:通信域,表明使用的是ipv4协议
 11     //参数2:通信方式,使用TCP通信
 12     //参数3:0表示之前已经指定协议 IPPROTO_TCP
 13 
 14     if(sfd == -1)
 15     {
 16         perror("socket error");
 17         return -1;
 18     }
 19     printf("sfd = %d\n", sfd);               //3
 20 
 21 
 22     //将端口号快速重用函数
 23     int reuse = 1;
 24     if(setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)) == -1)
 25     {
 26         perror("setsockopt error");
 27         return -1;
 28     }
 29     printf("端口号快速重用成功\n");
 30 
 31 
 32 
 33     //2、给当前套接字绑定IP地址和端口号
 34     //2.1填充要绑定的地址信息结构体
 35     struct sockaddr_in sin;
 36     sin.sin_family =     AF_INET;        //通信域
 37     sin.sin_port =         htons(SER_PORT);  //端口号
 38     sin.sin_addr.s_addr =     inet_addr(SER_IP);    //ip地址
 39 
 40     //2.2 绑定
 41     if(bind(sfd, (struct sockaddr*)&sin, sizeof(sin)) == -1)
 42     {
 43         perror("bind error");
 44         return -1;
 45     }
 46     printf("bind success %s %s %d\n", __FILE__, __func__, __LINE__);
 47 
 48     //3、将套接字设置成监听状态
 49     if(listen(sfd, 128) == -1)
 50     {
 51         perror("listen error");
 52         return -1;
 53     }
 54     printf("listen success %s %s %d\n", __FILE__, __func__, __LINE__);
 55 
 56     //4、阻塞等待客户端的链接请求
 57     //4.1定义容器接收客户端的地址信息
 58     struct sockaddr_in cin;                  //用于接收地址信息
 59     socklen_t socklen = sizeof(cin);          //用于接收地址信息的大小
 60 
 61     int newfd = -1;
 62 
 63 
 64     //11、定义一个等待文件描述符结构体数组
 65     struct pollfd pfd[2];
 66 
 67     //22、填充要等待的文件描述符及事件
 68     pfd[0].fd = 0;         //将0号文件描述符放入检测集合中
 69     pfd[0].events = POLLIN;    //表示检测该文件描述符的读事件
 70 
 71     pfd[1].fd = cfd;      //将cfd文件描述符放入检测集合中
 72     pfd[1].events = POLLIN;      //表示检测该文件描述符的读事件
 73 
 74 
 75     //定义一个地址信息结构体数组,每一个元素对应一个客户端文件描述符
 76     struct sockaddr_in cin_arr[1024];
 77 
 78 
 79 
 80     while(1)
 81     {
 82         //判断是否是文件描述符触发事件
 83         int res = poll(pfd,2,-1);
 84         if(res == -1)
 85         {
 86             perror("poll error");
 87             return -1;
 88         }else if(res == 0)
 89         {
 90             printf("timeout\n");
 91             return -1;
 92         }
 93 
 94             //程序执行至此,说明已经有事件产生并且解除了select的阻塞
 95             //判断哪个文件描述符还在集合中,如果在,就执行相关函数
 96                 //4.2 接收客户端的链接
 97                 newfd = accept(sfd, (struct sockaddr*)&cin, &socklen);
 98                 if(newfd == -1)
 99                 {
100                     perror("accept error");
101                     return -1;
102                 }
103                 printf("[%s:%d]发来链接请求 %s %s %d\n", \
104                         inet_ntoa(cin.sin_addr), ntohs(cin.sin_port),__FILE__, __func__, __LINE__);
105 
106                 //更新地址信息结构体数组
107                 cin_arr[newfd] = cin;
108 
109                     //终端输入
110                     char wbuf[128] = "";
111                     scanf("%s", wbuf);
112                     printf("触发了终端输入事件。。。\n");
113                     if(strcmp(wbuf, "quit") == 0)
114                     {
115                         break;
116                     }
117 
118                     //将消息发送给所有客户端
119                     for(int i=4; i<=maxfd; i++ )
120                     {
121                         sendto(i, wbuf, sizeof(wbuf), 0,(struct sockaddr*) &cin_arr[i], sizeof(cin_arr[i]));
122                     }
123 
124                     //5、跟客户端进行消息通信
125                     char buf[128] = "";
126 
127                     //将数组清空
128                     bzero(buf, sizeof(buf));
129 
130                     //读取客户端发来的消息
131                     //int res = read(newfd, buf, sizeof(buf));
132                     int res = recv(cli, buf, sizeof(buf), 0);
133                     if(res == 0)
134                     {
135                         printf("客户端已经下线\n");
136                         //关闭当前通信的套接字
137                         close(cli);
138                         //将当前文件描述符从文件描述符集合中移除
139                         FD_CLR(cli, &readfds);
140 
141                         //更新maxfd
142                         for(int i=maxfd; i>=sfd; i--)
143                         {
144                             if(FD_ISSET(i, &readfds))
145                             {
146                                 maxfd = i;
147                                 break;
148                             }
149                         }
150 
151 
152 
153                         continue;
154                     }
155                     printf("[%s:%d] : %s\n", inet_ntoa(cin_arr[cli].sin_addr), ntohs(cin_arr[cli].sin_port), buf);
156 
157                     //给客户端发消息
158                     strcat(buf, "*_*");
159 
160                     //write(newfd, buf, sizeof(buf));
161                     send(cli, buf, sizeof(buf), 0);
162                     printf("发送成功\n");
163 
164     }
165     //6、关闭套接字
166     close(sfd);
167 
168 
169 
170 
171 
172     return 0;
173 }
174 
~                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              
~                    

你可能感兴趣的:(单片机,嵌入式硬件)