[X]关闭

网络编程-2day

文档创建者:ぉ沙皮狗的忧伤
浏览次数:3963
最后更新:2021-03-08
本帖最后由 ぉ沙皮狗的忧伤 于 2021-3-10 10:22 编辑

TCP头格式
截图202103101012124031..png
三次握手,四次挥手
截图202103101017496393..png
S:连接性SYN=1,发起一个连接请求,调用connect()
A:应答位ACK=1,ack确定有效
F:断开位FIN=1,发送一个断开请求数据包,调用close

一、sever端代码编写
1、代码流程
        ①、socket建立流失套接字
        ②、signal改变该进程处理信号的方式
        ③、sockaddr_in成员初始化
        ④、bind绑定
        ⑤、listen设置为监听:被动连接
        ⑥、while循环,父进程等待连接,子进程处理已连接的客户端
2、添加头文件
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <unistd.h>
  4. #include <strings.h>
  5. #include <sys/types.h>
  6. #include <sys/socket.h>
  7. #include <netinet/in.h>
  8. #include <netinet/ip.h>
  9. #include <signal.h>
  10. #include <arpa/inet.h>
复制代码

编写main函数,TCP并发服务器:采用多进程
3、建立流失套接字
  1. //建立流失套接字
  2. //参数1----地址族,AF_INET网络协议族
  3. //参数2----套接字类型,SOCK_STREAM使用TCP
  4. //参数3----protocol参数通常设置0
  5. //返回值---成功socket ID,出错返回-1
  6. serfd = socket( AF_INET, SOCK_STREAM, 0);
  7. if(serfd < 0){
  8.     perror("socket failed!\n");
  9.     exit(1);
  10. }
复制代码


4、设备该进程的信号处理方式
  1. //忽略SIGCHLD信号的处理,内核自动回收8kb物理资源
  2. //子进程结束会发送一个SIGCHLD信号给内核
  3. //参数1-----要处理的信号
  4. //参数2-----处理的方式,SIG_IGN屏蔽该信号
  5. signal( SIGCHLD, SIG_IGN);
复制代码


5、绑定本地IP地址和指定接收数据端口,通过bind绑定套接字和端口

  1. struct sockaddr_in self;
  2. bzero( &self, sizeof(self));
  3. self.sin_family = AF_INET;                  //选择ipv4协议
  4. self.sin_port = htons(6666);                //选择端口
  5. self.sin_addr.s_addr = htonl(INADDR_ANY);        //内核自动绑定
  6. ret = bind( serfd, (struct sockaddr *)&self, sizeof(self));
  7. if( ret < 0){
  8.     perror("bind failed!\n");
  9.     exit(1);
  10. }
复制代码
6、设置为监听模式,被动连接
  1. //参数1----被监听的套接字
  2. //参数2----指定正在等待的最大队列长度
  3. //返回值0或-1
  4. ret = listen(serfd, 5);
  5. if(ret < 0){
  6.     perror("listen failed!\n");
  7.     exit(1);
  8. }
复制代码
7、使用一个while循环,父进程等待连接,子进程处理客户端数据
  1. while(1){
  2.     printf("wait client!\n");
  3.     //5、父进程等待连接
  4.     newfd = accept( serfd, (struct sockaddr *)&cli, &len);
  5.     if(newfd < 0){
  6.          perror("accept failed!\n");
  7.          exit(1);
  8.      }
  9.      printf("new client ip = %s port = %d ok\n", inet_ntoa(cli.sin_addr),\
  10.           ntohs(cli.sin_port));
  11.      //6、创建一个子进程
  12.      pid_t pid = fork();
  13.      if(pid < 0){
  14.          perror("fork failed!\n");
  15.          exit(1);
  16.      }
  17.      if(pid > 0)
  18.          continue;
  19.       //子进程执行代码块
  20.       if(pid == 0){
  21.           //处理已连接客户端数据
  22.           char buf[128];
  23.           int ret = -1;
  24.           while(1){
  25.               bzero( buf, 128);
  26.               ret = read( newfd, buf, 127);
  27.               if(ret < 0){
  28.                   perror("read");
  29.                   exit(1);
  30.           }
  31.                                 
  32.           //如果客户端输入quit或者Cttl+C关闭,服务器也会关闭
  33.           if(!strncmp( buf, "quit", 4) || (buf[0] == 0)){
  34.               close(newfd);
  35.               break;
  36.           }
  37.           printf("ip = %s port = %d buf = %s\n", inet_ntoa(cli.sin_addr),\
  38.               ntohs(cli.sin_port), buf);
  39.           }
  40.            exit(1);    //结束当前进程               
  41.      }         
  42. }
  43.         
复制代码

二、client端代码编写1、添加头文件
  1. #include <string.h>
  2. #include <strings.h>
  3. #include <stdlib.h>
  4. #include <unistd.h>
  5. #include <stdio.h>
  6. #include <sys/types.h>
  7. #include <sys/socket.h>
  8. #include <netinet/in.h>
  9. #include <netinet/ip.h>
  10. #include <arpa/inet.h>
复制代码
2,创建流失套接字
  1.         //创建流失套接字
  2.         //参数1----地址族,AF_INET网络协议族
  3.         //参数2----套接字类型,SOCK_STREAM使用tcp
  4.         //参数3----protocol通常设置为0
  5.         //返回值---成功socket id 失败 -1
  6.         clifd = socket( AF_INET, SOCK_STREAM, 0);
  7.         if(clifd < 0){
  8.                 perror("socket failed!\n");
  9.                 exit(1);
  10.         }
复制代码
3、主动连接服务器:指定服务器IP和接收端口
  1.         //主动连接服务器:指定服务器IP和接收端口
  2.         struct sockaddr_in ser;
  3.         bzero( &ser, sizeof(ser));
  4.         ser.sin_family = AF_INET;                  //AF_INET网络协议族
  5.         ser.sin_port = htons(6666);                 //要连接的服务器端口
  6.         ser.sin_addr.s_addr = inet_addr("172.18.12.163");    //服务器ip
  7.         ret = connect( clifd, (struct sockaddr *)&ser, sizeof(ser));
  8.         if(ret < 0){
  9.                 perror("connect failed!\n");
  10.                 exit(1);
  11.         }
复制代码
4、发送数据,从标准输入获取键盘的值
  1. while(1){
  2.     fprintf( stderr, "input:");
  3.     bzero( buf, 128);
  4.     //从标准输入获取字符串
  5.     fgets( buf, 127, stdin);
  6.     //写入套接字中
  7.     ret = write( clifd, buf, strlen(buf));
  8.     if(ret < 0){
  9.       perror("write failed!\n");
  10.       exit(1);
  11.     }
  12.     if(!strncmp( buf, "quit", 4)){
  13.       break;
  14.     }
  15. }
复制代码
三、使用gcc编译sever端代码,在虚拟机上运行,使用交叉编译工具编译client端代码,在板卡上运行 截图202103100944564594..png

四、运行可执行程序
截图202103100946468023..png

代码在附件中。。。。

tcp_core.tar.gz

8.04 KB, 下载次数: 154

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则