• 一个简单的 socket 网络编程


    1 socket编程流程

    1.1 创建socket

    int socket(int domain, int type, int protocol);
    

    domain 用于指定底层协议族,对 TCP/IP 协议族来说,应设置为 PF_INET(IPv4)或 PF_INET6(IPv6);type 用于指定服务类型,对 TCP/IP 族来说,SOCK_STREAM 表示使用 TCP 协议,SOCK_STREAM 表示使用 UDP 协议;protocol 是再选择一个具体的协议,一般设为 0 使用默认协议即可。

    1.2 命名socket

    在服务端,需要调用 bind 将 socket 与 socket 地址进行绑定,在客户端则不需要调用 bind 进行绑定,操作系统会自动分配地址,当然也可以自行调用 bind 进行地址绑定,但是没有那个必要。

    int bind(int sockfd, const struct sockaddr* my_addr, socklen_t addrlen);
    

    所有专用 socket 地址(比如 TCP/IP 协议族的 sockaddr_in 和 sockaddr_in6 等)在使用时都需要转换为通用 socket 地址 sockaddr, 所以在传入第二个参数时往往需要进行强制转换。

    1.3 监听socket

    调用 listen 指定被监听的 socket 和监听队列的最大长度。

    int listen(int sockfd, int backlog);
    

      

    1.4 接受连接

    int accept(int sockfd, struct sockaddr* addr, socklen_t* addrlen);
    

      

    1.5 发起连接

    客户端通过 connect 与服务器建立连接。

    int connect(int sockfd, const struct sockaddr* serv_addr, socklen_t addrlen);
    

      

    2 代码示例

    2.1 服务端

    #include<stdio.h>
    #include<stdlib.h>
    #include<assert.h>
    #include<string.h>
    #include<errno.h>
    #include<unistd.h>
    #include<sys/socket.h> 
    #include<arpa/inet.h>
    
    const int BUFSIZE = 1024;
    
    int main(int argc, char* argv[]){
    
        if(argc <= 3){
            printf("usage: %s ip_adderss port number backlog\n", basename(argv[0]));
            return 1;
        }
    
        const char *ip = argv[1];
        int port = atoi(argv[2]);  //字符串转换整数
        int backlog = atoi(argv[3]);
    
        /*创建socket*/
        int sockfd = socket(PF_INET, SOCK_STREAM, 0);
        assert(sockfd >= 0);
    
        /*创建socket地址*/
        struct sockaddr_in address;
        bzero(&address, sizeof(address));
        address.sin_family = AF_INET;
        address.sin_port = htons(port);  //主机字节序转换网络字节序
        inet_pton(AF_INET, ip, &address.sin_addr);
    
        int ret = bind(sockfd, (struct sockaddr*) &address, sizeof(address));  //绑定socket地址
        assert(ret != -1);
    
        /*监听socket*/
        ret = listen(sockfd, backlog);
        assert(ret != -1);
    
        printf("Waiting for connection...\n");
    
        struct sockaddr_in client;
        
        while(true){
            
            socklen_t client_length = sizeof(client);
            /*accept连接*/
            int connfd = accept(sockfd, (struct sockaddr *)&client, &client_length); 
            if(connfd < 0){
                printf("errno is: %d\n", errno);
                break;
            }
    
            printf("From client: IP is %s and Port is %d\n", inet_ntoa(client.sin_addr), ntohs(client.sin_port));  //输出客户端IP和端口
    
            /*数据读写*/
            char recv_buffer[BUFSIZE];
            int n = recv(connfd, recv_buffer, BUFSIZE, 0);
            recv_buffer[n] = '\0';
            printf("Got %d bytes of data: %s\n", n, recv_buffer);
    
            close(connfd);
        }
    
        close(sockfd);
    
        return 0;
    }
    

      

    2.2 客户端

    #include<stdio.h>
    #include<stdlib.h>
    #include<assert.h>
    #include<string.h>
    #include<errno.h>
    #include<unistd.h>
    #include<sys/socket.h> 
    #include<arpa/inet.h>
    
    const int BUFSIZE = 1024;
    
    int main(int argc, char* argv[]){
    
        if(argc <= 2){
            printf("usage: %s ip_adderss port number\n", basename(argv[0]));
            return 1;
        }
    
        const char *ip = argv[1];
        int port = atoi(argv[2]);  //字符串转换整数
    
        /*创建socket*/
        int sockfd = socket(PF_INET, SOCK_STREAM, 0);
        assert(sockfd >= 0);
    
        /*创建socket地址*/
        struct sockaddr_in address;
        bzero(&address, sizeof(address));
        address.sin_family = AF_INET;
        address.sin_port = htons(port);  //主机字节序转换网络字节序
        inet_pton(AF_INET, ip, &address.sin_addr);
    
        /*发起连接*/
        if(connect(sockfd, (struct sockaddr *)&address, sizeof(address)) < 0){
            printf("Connection failed\n");
            exit(1);
        }
    
        /*数据读写*/
        printf("Please enter information to the server:\n");
        char send_buffer[BUFSIZE];
        fgets(send_buffer, BUFSIZE, stdin);
        if(send(sockfd, send_buffer, strlen(send_buffer), 0) < 0){
            printf("errno is: %d\n", errno);
            exit(1);
        }
    
        close(sockfd);
        return 0;
    }
    

      

  • 相关阅读:
    Redis的安装和部署
    SaltStack应用grains和jinja模板-第四篇
    SaltStack部署配置Tomcat-第三篇
    python魔法方法、构造函数、序列与映射、迭代器、生成器
    python异常
    python类
    python之函数、参数、作用域、递归
    docker+openvswitch实现主机与容器的网络通信
    Docker网络和容器的通信
    docker命名空间、控制组及联合文件系统概念
  • 原文地址:https://www.cnblogs.com/zyb993963526/p/16054626.html
Copyright © 2020-2023  润新知