zoukankan      html  css  js  c++  java
  • linux 下socket编程

    原理

    1. 类unix系统中, 一切皆文件, 诸如磁盘文件, 显卡, 内核驱动, 网络协议栈等
    2. socket就是linux中提供的用于网络通信的文件接口, 两台机器之间可以读写消息
    3. 在使用socket真正的通信之前, 需要先建立连接, 连接的建立根据协议的不同, 建立的过程也不一样, 目前支持tcp, udp 协议, 通过raw socket, 也可以直接访问网络层的数据包, 更多可参考 http://man7.org/linux/man-pages/man2/socket.2.html

    基本使用

    功能

    基于tcp, 实现一个echo 服务器, 回复客户端后, 直接关闭连接

    测试

    编译后, 先运行服务端(要有root权限); 用nc或者telnet, 连接监听的端口(示例中使用的是90) , 发送一条消息

    示例

    #include<stdio.h>   //定义了标准库的文件流操作的函数, 也定义了如printf, perror等
    #include<stdlib.h>  //定义了很多辅助性的函数, 其中包括exit
    #include<unistd.h>  //定义了文件操作的函数, 如close
    #include<sys/types.h>  //定义了一些u_short, u_int, pid_t之类的数据类型, 为了保持和旧系统的兼容性, socket编程非必要, 参见man socket, NOTE段 
    #include<sys/socket.h> //定义bind, listen, accept等函数 
    #include<netinet/in.h> //定义了ip地址的结构体
    #include<arpa/inet.h> //定义了ip地址转换的函数, 如inet_pton, inet_ntop
    #include<errno.h>
    
    
    void err_exit(const char* msg){
        int old_errno = errno;
        perror(msg);
        exit(old_errno);
    }
    
    
    int main(void){
        //从系统中申请socket句柄, 占用一个进程的文件描述符
        int serv_sock_fd = socket(AF_INET, SOCK_STREAM, 0);
    
        int on = 1;
        // 避免客户端和服务端在同台机器上, 如果先没有正常关闭socket, 导致的address already in use 的错误, 非必须
        setsockopt(serv_sock_fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
    
            //定义连接需要的结构体, 里面会声明连接将要使用的协议, 支持AF_INET(ipv4), AF_INET6(ipv6), AF_UNIX(unix域套接字)等
            //结构体要置零, 避免未知的错误
        struct sockaddr_in serv_addr = {0};
    
        serv_addr.sin_family = AF_INET;
        //设置ip地址和端口时, 需要将值转换为网络字节序
        inet_pton(AF_INET, "127.0.0.1", &serv_addr.sin_addr);
        serv_addr.sin_port = htons(90);
    
        //先要将socket和对应的连接协议信息进行绑定
        if(bind(serv_sock_fd, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) < 0){
            err_exit("socket bind failed");
        }
    
        //然后开始监听, 协议指定的地址和端口
        // listen的第二个参数, 请参考man 2 listen; 暂时设置为5
        // listen成功返回之后, 客户端就可以进行连接了
        if(listen(serv_sock_fd, 5) < 0){
            err_exit("socket listen failed");
        }
    
        int clnt_sock_fd = -1;
        char buffer[1024] = {0};
        while(1){
            //通过accept调用来获取已连接的客户端; 如果没有连接, 则阻塞,直到有连接进来
            clnt_sock_fd = accept(serv_sock_fd, 0, 0);
            if (clnt_sock_fd < 0){
                err_exit("accept failed");
            }
    
            //客户端成功连接后, 就可以在socket上, 进行读写(也可以称作发送和接收)了, 可以使用write/read方法, 也可以使用send/recv(请参看man 2 send)
            recv(clnt_sock_fd, buffer, sizeof(buffer), 0);
            send(clnt_sock_fd, buffer, sizeof(buffer), 0); 
    
            //完成响应后, 直接关闭客户端的连接
            close(clnt_sock_fd);
        }
    }
  • 相关阅读:
    Mac安装zookeeper
    征途
    vue-配置文件
    数组去重
    判断身份证
    判断邮箱
    判断手机号是否正确
    JS 时间格式转换
    打印 print-js
    自"愚"自乐的云服务器
  • 原文地址:https://www.cnblogs.com/zhedan/p/7627200.html
Copyright © 2011-2022 走看看