ぉ沙皮狗的忧伤 发表于 2021-3-8 18:26:03

网络编程-2day

本帖最后由 ぉ沙皮狗的忧伤 于 2021-3-10 10:22 编辑

TCP头格式

三次握手,四次挥手

S:连接性SYN=1,发起一个连接请求,调用connect()
A:应答位ACK=1,ack确定有效
F:断开位FIN=1,发送一个断开请求数据包,调用close

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

#include <netinet/in.h>
#include <netinet/ip.h>

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

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


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

struct sockaddr_in self;
bzero( &self, sizeof(self));

self.sin_family = AF_INET;                  //选择ipv4协议
self.sin_port = htons(6666);                //选择端口
self.sin_addr.s_addr = htonl(INADDR_ANY);      //内核自动绑定

ret = bind( serfd, (struct sockaddr *)&self, sizeof(self));
if( ret < 0){
    perror("bind failed!\n");
    exit(1);
}6、设置为监听模式,被动连接
//参数1----被监听的套接字
//参数2----指定正在等待的最大队列长度
//返回值0或-1
ret = listen(serfd, 5);
if(ret < 0){
    perror("listen failed!\n");
    exit(1);
}
7、使用一个while循环,父进程等待连接,子进程处理客户端数据
while(1){

    printf("wait client!\n");
    //5、父进程等待连接
    newfd = accept( serfd, (struct sockaddr *)&cli, &len);
    if(newfd < 0){
         perror("accept failed!\n");
         exit(1);
   }

   printf("new client ip = %s port = %d ok\n", inet_ntoa(cli.sin_addr),\
          ntohs(cli.sin_port));

   //6、创建一个子进程
   pid_t pid = fork();
   if(pid < 0){
         perror("fork failed!\n");
         exit(1);
   }

   if(pid > 0)
         continue;

      //子进程执行代码块
      if(pid == 0){
          //处理已连接客户端数据
          char buf;
          int ret = -1;

          while(1){
            bzero( buf, 128);
            ret = read( newfd, buf, 127);
            if(ret < 0){
                  perror("read");
                  exit(1);
          }
                              
          //如果客户端输入quit或者Cttl+C关闭,服务器也会关闭
          if(!strncmp( buf, "quit", 4) || (buf == 0)){
            close(newfd);
            break;
          }

          printf("ip = %s port = %d buf = %s\n", inet_ntoa(cli.sin_addr),\
            ntohs(cli.sin_port), buf);

          }
         exit(1);    //结束当前进程               
   }         
}
      
二、client端代码编写1、添加头文件
#include <string.h>
#include <strings.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>

#include <netinet/in.h>
#include <netinet/ip.h>


#include <arpa/inet.h>2,创建流失套接字
      //创建流失套接字
      //参数1----地址族,AF_INET网络协议族
      //参数2----套接字类型,SOCK_STREAM使用tcp
      //参数3----protocol通常设置为0
      //返回值---成功socket id 失败 -1
      clifd = socket( AF_INET, SOCK_STREAM, 0);
      if(clifd < 0){
                perror("socket failed!\n");
                exit(1);
      }3、主动连接服务器:指定服务器IP和接收端口
      //主动连接服务器:指定服务器IP和接收端口
      struct sockaddr_in ser;
      bzero( &ser, sizeof(ser));

      ser.sin_family = AF_INET;                  //AF_INET网络协议族
      ser.sin_port = htons(6666);               //要连接的服务器端口
      ser.sin_addr.s_addr = inet_addr("172.18.12.163");    //服务器ip

      ret = connect( clifd, (struct sockaddr *)&ser, sizeof(ser));
      if(ret < 0){
                perror("connect failed!\n");
                exit(1);
      }4、发送数据,从标准输入获取键盘的值
while(1){
    fprintf( stderr, "input:");
    bzero( buf, 128);
    //从标准输入获取字符串
    fgets( buf, 127, stdin);

    //写入套接字中
    ret = write( clifd, buf, strlen(buf));
    if(ret < 0){
      perror("write failed!\n");
      exit(1);
    }

    if(!strncmp( buf, "quit", 4)){
      break;
    }

}三、使用gcc编译sever端代码,在虚拟机上运行,使用交叉编译工具编译client端代码,在板卡上运行

四、运行可执行程序


代码在附件中。。。。
页: [1]
查看完整版本: 网络编程-2day