Linux网络编程 之 TCP编程(七)

目录
1. TCP客户端
- 核心函数
- 完整的TCP客户端程序
2. TCP服务端
- 核心函数
- 完整的TCP客户端程序


TCP编程的核心步骤和流程:
这里写图片描述

1. TCP客户端

核心函数:

  1. 创建一个套接字:
int socket(int family,int type,int protocol);
  • family: 套接字域
  • type: 套接字类型
  • protocol 套接字协议

    1. 向服务器发送连接请求:
 int connect( int sockfd, 
              const struct sockaddr *addr, 
              socklen_t len );
  • sockfd:套接字描述符
  • addr: 连接的服务器地址结构
  • len: 地址结构体长度

    1. 向服务器发送数据:
 ssize_t send(int sockfd, 
             const void* buf, 
             size_t nbytes,
             int flags);
  • sockfd: 已建立连接的套接字描述符
  • buf: 发送数据的地址
  • nbytes: 发送缓数据的大小(以字节为单位)
  • flags: 套接字标志(常为 0)

完整的UDP客户端程序

#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <netinet/in.h>
int main(int argc, char *argv[])
{
    unsigned short port;   // 服务器的端口号
    char *server_ip ;       // 服务器ip地址

    if( argc > 1 )      //函数传参                                  
    {       
        server_ip = argv[1];
    }   
    if( argc > 2 )     //函数传参                                   
    {
        port = atoi(argv[2]);
    }

    int sockfd;
    sockfd = socket(AF_INET, SOCK_STREAM, 0);// 创建通信端点:套接字
    if(sockfd < 0)
    {
        perror("socket");
        exit(-1);
    }

    // 设置服务器地址结构体
    struct sockaddr_in server_addr;
    bzero(&server_addr,sizeof(server_addr)); // 初始化服务器地址
    server_addr.sin_family = AF_INET;   // IPv4
    server_addr.sin_port = htons(port); // 端口
    //inet_pton(AF_INET, server_ip, &server_addr.sin_addr); // ip
    server_addr.sin_addr.s_addr = inet_addr(server_ip);//与inet_pton等价

     // 主动连接服务器
    int err_log = connect(sockfd, (struct sockaddr*)&server_addr, sizeof(server_addr));     
    if(err_log != 0)
    {
        perror("connect");
        close(sockfd);
        exit(-1);
    }


    printf("send data to %s:%d\n",server_ip,port);

    char send_buf[512] = "this is send data";
    printf("send data \"%s \" to %s:%d\n",send_buf,server_ip,port);
    send(sockfd, send_buf, strlen(send_buf), 0);   // 向服务器发送信息

    char recv_buf[512] = {0};
    recv(sockfd, recv_buf, sizeof(send_buf), 0); // 接收数据
    printf("%s\n", recv_buf);

    close(sockfd);

    return 0;
}

2. TCP服务端

核心函数:

  1. 本地协议地址与 sockfd 绑定,这样 ip、port 就固定了
int bind( int sockfd, 
          const struct sockaddr *myaddr,
          socklen_t addrlen );
  • sockfd:socket 套接字
  • myaddr: 指向特定协议的地址结构指针
  • addrlen:该地址结构的长度

    1. 将套接字由主动修改为被动,使操作系统为该套接字设置一个连接队列
int listen(int sockfd, int backlog);
  • sockfd: socket监听套接字
  • backlog:连接队列的长度

    1. 如果没有连接可用,则进入阻塞状态,如果有连接可用则取出一个已经建立的连接
int accept(  int sockfd,
             struct sockaddr *cliaddr, 
             socklen_t *addrlen );
  • sockfd: socket监听套接字
  • cliaddr: 用于存放客户端套接字地址结构
  • addrlen: 套接字地址结构体长度的地址

完整的UDP服务端程序

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>                     
    #include <unistd.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <arpa/inet.h>              
    int main(int argc, char *argv[])
    {
        unsigned short port = 8000; // 本地端口 
        if(argc > 1)                        
        {
            port = atoi(argv[1]);
        }
        //1.创建通信端点:套接字
        int sockfd = socket(AF_INET, SOCK_STREAM, 0);   
        if(sockfd < 0)
        {
            perror("socket");
            exit(-1);
        }

        //设置本地地址结构体
        struct sockaddr_in my_addr;
        bzero(&my_addr, sizeof(my_addr));           // 清空,保证最后8字节为0    
        my_addr.sin_family = AF_INET;               // ipv4
        my_addr.sin_port   = htons(port);           // 端口
        my_addr.sin_addr.s_addr = htonl(INADDR_ANY);// ip,INADDR_ANY为通配地址其值为0

        //2.绑定:将本地ip、端口与套接字socket相关联起来
        int err_log = bind(sockfd, (struct sockaddr*)&my_addr, sizeof(my_addr));
        if( err_log != 0)
        {
            perror("binding");
            close(sockfd);      
            exit(-1);
        }

        //3.监听,监听套接字改为被动,创建连接队列
        err_log = listen(sockfd, 10); 
        if(err_log != 0)
        {
            perror("listen");
            close(sockfd);      
            exit(-1);
        }   

        printf("listen client @port=%d...\n",port);

        while(1)
        {   

            struct sockaddr_in client_addr;        
            char cli_ip[INET_ADDRSTRLEN] = "";     
            socklen_t cliaddr_len = sizeof(client_addr);    

            int connfd = 0;

            //4.从完成连接队列中提取客户端连接
            connfd = accept(sockfd, (struct sockaddr*)&client_addr, &cliaddr_len);       
            if(connfd < 0)
            {
                perror("accept");
                continue;
            }

            inet_ntop(AF_INET, &client_addr.sin_addr, cli_ip, INET_ADDRSTRLEN);
            printf("----------------------------------------------\n");
            printf("client ip=%s,port=%d\n", cli_ip,ntohs(client_addr.sin_port));

            char recv_buf[512] = "";
            while( recv(connfd, recv_buf, sizeof(recv_buf), 0) > 0 ) // 接收数据
            {
                printf("\nrecv data:\n");
                printf("%s\n",recv_buf);
            }

            close(connfd);     //关闭已连接套接字
            printf("client closed!\n");
        }

        close(sockfd);         //关闭监听套接字

        return 0;
    }

猜你喜欢

转载自blog.csdn.net/qq_33394088/article/details/80922685
今日推荐