Linux's TCP program

TCP is a TCP / IP protocol suite a reliable connection-oriented protocol , which will be described herein, the workflow methods and be programmed in Linux.

TCP foundation

TCP provides services to the neighboring high-rise. The TCP layer is the application layer, and thus, to achieve a TCP data transfer from a data transfer application to another application.
TCP application calls by using TCP programming and services to provide the data to be ready to send, used to distinguish the destination address and port number of the received data applications.
Normally, applications to use the service by opening a TCP socket, TCP data transfer management to the other socket.
Can uniquely distinguish two devices connected to the network through the IP source / destination, the network connection can be divided into two by a socket application source / destination uniquely.

TCP session handshake initialized by three times.
The purpose is to make three-way handshake to send and receive data segment sync, tell the other host can receive data amount of time, and to establish a virtual connection.

Three-way handshake is a simple process:

  1. Initialize master synchronization flag is set by a data segment sent session request.
  2. Receiving a data segment having a host by sending back the items expressed in response to: the synchronization flag is set, the starting sequence number to be sent Yu section of data segments, and the response with the sequence number of the next byte of the received data segment.
  3. Teach the requesting host sends a data return period, and an acknowledgment sequence number and acknowledgment numbers.

TCP three-way handshake procedure a schematic
Here Insert Picture Description basic TCP protocol entity uses a sliding window protocol, when the sender transmits a datagram, it starts a timer. When the datagram reaches the destination, TCP entity receiving side sends back a data packet that contains an acknowledgment sequence number indicating the sequence number of the next desired data packet received. If the sender of the acknowledgment timer expires before the message arrives, the sender retransmits the packet.

TCP header format of
Here Insert Picture Description its various parts as follows:

  • 源端口,目的端口:16位长,标识出远端和本地的端口号。
  • 序号:32位长,标识发送数据报的顺序。
  • 确认号:32位长,希望收到的下一个数据包的序列号,
  • TCP头长:4位长,表明 TCP 头中包含多少个 32 位字。
  • 6 位未用。
  • ACK:ACK位置 1 表明确认号是合法的,如果 ACK 为0,那么教据报不包含确认信息,确认字段被省略。
  • PSH:表示是带有 PUSH 标志的数据,接收方只等请求数据包一到便将其送往应用程序而不必等到缓冲区装满时才传送。
  • RST:用于复位由于主机崩溃或其他原因而出现的错误连接,还可以用于拒绝非法的数据包或拒绝连接请求。
  • SYN:用于建立连接
  • FIN:用于释放连接。
  • 窗口大小:16位长,窗口大小字段表示在确认了字节之后还可以发送多个字节。
  • 校验和:16位长,是为了确保高可靠性而设置的,用于校验头部、数据和伪 TCP 头部之和。
  • 可选项:0个或多个32位字,包括最大 TCP 载荷、滑动窗口比例以及选择重发数据包等选项。

TCP 的工作流程

基于 TCP 传输协议的服务器与客户端间的通信工作流程可以利用下图所示的过程来描述。
Here Insert Picture Description

  1. 服务器先用 socket 函数来建立一个套接口,用这个套接口完成通信的监听及数据的收发。
  2. 服务器利用 bind 函数来绑定一个端口号和 IP 地址,使套接口与指定的端口号、IP 地址相关联。
  3. 服务器调用 listen 函数, 使服务器的这个端口和 IP 处于监听状态,等待网络中某一客户机的连接请求。
  4. 客户机用 socket 函数建立一个套接口,设定远程 IP 和端口。
  5. 客户机调用 connect 函数连接远程计算机指定的端口。
  6. 服务器调用 accept 函数来接收远程计算机的连接请求,建立起与客户机之间的通信连接。
  7. 建立连接以后,客户机利用 write 函数或 send 函数向 socket 中写入数据,也可以使用 read 函数或 recv 函数读取服务器发送来的数据。
  8. 服务器利用 read函数或 recv 函数读取客户机发送来的数据,也可以利用 write 函数或 send 函数来发送数据。
  9. After the completion of the communication, using the close function and socket connection.

Applications

Examples 1 and 2 is an example of the application using TCP server and client communications: the server receives a client request, creates a child process the current system time is transmitted to the client; server sends the client information is read .

[] 1 case of TCP communication server-side
application code uses 25555 port as the communication port, and the first socket function call function to create a socket and bind bound port, and then listen function call connection requests from clients, if the client's connection information, use the accept function receives the connection and create a child process, send the current time information in the child, and finally close the socket interface when the child process exits.

code show as below:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <time.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>

#define SERV_PORT 25555  //服务器接听端口号
#define BACKLOG 20  //请求队列中允许请求数
#define BUF_SIZE 256  //缓冲区大小

int main(int arge,char *argv[])
{
  int ret;
  time_t tt;
  struct tm *ttm;
  char buf[BUF_SIZE];
  pid_t pid; //定义管道描述符
  int sockfd;//定义 sock 描述符
  int clientfd; //定义数据传输 sock 描述符
  struct sockaddr_in host _addr;//本机IP地址和端口信息
  struct sockaddr_in client_addr;//客户端IP地址和端口信息
  int length = sizeof client_addr;
  //创建套接字
  sockfd = socket(AF_INET, SOCK_STREAM, 0);//TCP/IP协议,数据流套接字
  if(sockfd == -1)//判断socket函数的返回值
  {
    printf("创建socket失败!\n");
    return 0;
  }
  //绑定套接字
  bzero(&host_addr, sizeof host_addr);
  host_addr.sin_family = AF_INET;//TCP/IP协议
  host_addr.sin_port = htons(SERV_PORT);//设定端口号
  host_addr.sin_addr.s_addr = INADDR_ANY;//本地IP地址
  ret = bind(sockfd, (struct sockaddr *)&host_addr, sizeof host_addr); //绑定套接字
  if(ret == -1) //判断bind函数的返回值
  {
    printf("调用bind失败!\n");
    return 1;
  }
  //监听网络端口
  ret = listen(sockfd, BACKLOG);
  if(ret==-1)//判断listen函数的返回值
  {
    printf("调用listen函数失败.\n");
    return 1;
  }
  while(1)
  {
    clientfd = accept(sockfd,(struct sockaddr*)&client_addr, &length);//接收连接请求
    if(clientfd = -1)
    {
      printf("调用accept接受连接失败.\n");
      return 1;
    }
    pid = fork();//创建子进程
    if(pid == 0)//在子进程中处理
    {
      while(1)
      {
        bzero(buf, sizeof buf);//首先清空缓冲区
        tt = time(NULL);
        ttm = localtime(&tt);//获取当前时间参数
        strcpy(buf, asctime(ttm));//将时间信息 copy 进缓冲区
        send(clientfd, buf, strlen(buf), 0);//发送数据
        sleep(2);
      }
      close(clientfd);//调用close函数关闭连接
    else if(pid> 0)
    {
      close(clientfd);//父进程关闭套接字,准备下一个客户端连接
    }
  }
  return 0;
}

[2 Example] TCP client communication program
using argv [1] as an IP address for the connection, the IP address into the address specified by serv_addr structural body, and the connection using the connect function server creates a socket after use recv receiving time information sent from the server and print output.

code show as below:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>

#define SERV_PORT 25555 //服务器接听端口号
#define BACKLOG  20  //请求队列中允许请求数
#define BUF_SIZE 256    //缓冲区大小

int main(int arge, char *argv[])
{
  int ret;
  char buf[BUF_SIZEI];
  int sockfd;  //定义 sock 描述符
  struct sockaddr_in serv_addr;  //服务器 IP 地址和端口信息
  if(argc != 2)
  {
    print("命令行输入有误.\n");//命令行带IP
    returm 1;
  }
  //创建套接字
  sockfd = socket(AF_INET, SOCK_STREAM, 0);//TCP/IP协议,数据流套接字
  if(sockfd = -1)
  {
    printf("调用socket函数失败.\n");
    return 2;
  }
  //建立连接
  bzero(&serv_addr, sizeof serv_addr);
  serv_addr.sin_family = AF_INET;//TCP/IP协议
  serv_addr.sin_port = htons(SERV_PORT);//设定端口号
  //serv_ addr sin addr.s_ addr = INADDR ANY;//使用回环地址127.0.0.1
  inet_aton(argv[1], (struct sockaddr *)&serv_addr.sin_addr.s_addr);//设定IP地址
  ret = connect(sockfd, (struct sockaddr *)&serv_addr, sizeof serv_ addr); //绑定套接子
  if(ret==-1)
  {
    printf("调用connect函数失败.\n");
    return 3;
  }
  while(1)
  {
    bzero(buf, sizeof buf);
    recv(sockfd, buf, sizeof(buf), 0);//接收数据
    printf("接收到: %s", buf);
    sleep(1);
  }
  close(sockfd); //关闭链接
  return 0;
}

Performing the above two generation programs are two different terminals in the executable file, the output time can be seen.

Published 70 original articles · won praise 131 · views 20000 +

Guess you like

Origin blog.csdn.net/qq_43239560/article/details/103384044