查看: 1141|回复: 0

[评测分享] 【米尔-STM32MP135入门级开发板测评】 6.Socket编程

[复制链接]
  • TA的每日心情
    奋斗
    2024-4-19 21:11
  • 签到天数: 66 天

    连续签到: 1 天

    [LV.6]常住居民II

    发表于 2023-10-4 00:47:48 | 显示全部楼层 |阅读模式
    分享到:
    本帖最后由 feifeiz 于 2023-10-4 00:51 编辑

      
    1. Socket 简介
    套接字(socket)是 Linux 下的一种进程间通信机制(socket IPC),使用 socket IPC 可以使得在不同主机上的应用程序之间进行通信(**通信),当然也可以是同一台主机上 的不同应用程序。socket IPC 通常使用客户端<--->服务器这种模式完成通信,多个客户端可以同时连接到服务器中,与服务器之间完成数据交互。 内核向应用层提供了 socket 接口,调用 socket 接口开发自己的应用程序即可!socket 是应用层与 TCP/IP 协议通信的中间软件抽象层,它是一组接口。socket 其实就是一个门面模式,它把复杂的 TCP/IP 协议隐藏在 socket 接口后面,对用户来说,一组简单的 接口就是全部,让 socket 去组织数据,以符合指定的协议。当前**中的主流程序设计都是使用 socket 进行编程的,因为它简单易用,它还是一个标准(BSD socket),能在不同**很方便移植,比如你的一个应用程序是基于 socket 接口编写的,那么它可以移植到任何实现 BSD socket 标准的**。

    2.  Socket 接口

    1. **创建套接字 (`socket()`)**:
       - 函数原型:`int socket(int domain, inttype, int protocol);`
       - 用途:创建一个新的套接字,返回一个套接字描述符。
       - 参数:
         - `domain`:套接字的协议族,通常是 `AF_INET`(IPv4)或 `AF_INET6`(IPv6)。
         - `type`:套接字的类型,通常是 `SOCK_STREAM`(流套接字)或 `SOCK_DGRAM`(数据报套接字)。
         - `protocol`:套接字的协议,通常可以设置为0,由系统自动选择合适的协议。
       - 示例:
         intserver_socket = socket(AF_INET, SOCK_STREAM, 0);

    2. **绑定套接字到地址和端口 (`bind()`)**:
       - 函数原型:`int bind(int sockfd, conststruct sockaddr *addr, socklen_t addrlen);`
       - 用途:将套接字绑定到特定的IP地址和端口号。
       - 参数:
         - `sockfd`:套接字描述符。
         - `addr`:一个 `struct sockaddr` 结构,指定了要绑定的地址和端口。
         - `addrlen`:`addr` 结构的长度。
       - 示例:
         structsockaddr_in server_addr;
        server_addr.sin_family = AF_INET;
        server_addr.sin_port = htons(8080); // 使用8080端口
        server_addr.sin_addr.s_addr = INADDR_ANY;
        bind(server_socket, (struct sockaddr*)&server_addr,sizeof(server_addr));


    3. **启动服务器监听 (`listen()`)**:
       - 函数原型:`int listen(int sockfd, intbacklog);`
       - 用途:仅用于服务器套接字,用于启动监听模式,以等待客户端连接请求。
       - 参数:
         - `sockfd`:服务器套接字描述符。
         - `backlog`:等待连接队列的最大长度,指定同时能处理多少个等待连接的客户端。
       - 示例:
        listen(server_socket, 5);  // 允许最多5个等待连接的客户端

    4. **接受客户端连接请求 (`accept()`)**:
       - 函数原型:`int accept(int sockfd, structsockaddr *addr, socklen_t *addrlen);`
       - 用途:仅用于服务器套接字,用于接受客户端的连接请求,返回一个新的套接字描述符,用于与客户端通信。
       - 参数:
         - `sockfd`:服务器套接字描述符。
         - `addr`:一个 `struct sockaddr` 结构,用于存储客户端的地址信息。
         - `addrlen`:`addr` 结构的长度。
       - 示例:
         intclient_socket;
         structsockaddr_in client_addr;
         socklen_tclient_addr_len = sizeof(client_addr);
         client_socket =accept(server_socket, (struct sockaddr*)&client_addr,&client_addr_len);

    5. **客户端连接服务器 (`connect()`)**:
       - 函数原型:`int connect(int sockfd, conststruct sockaddr *addr, socklen_t addrlen);`
       - 用途:用于客户端套接字,用于连接到服务器的指定地址和端口。
       - 参数:
         - `sockfd`:客户端套接字描述符。
         - `addr`:一个 `struct sockaddr` 结构,指定了服务器的地址和端口。
         - `addrlen`:`addr` 结构的长度。
       - 示例:
         structsockaddr_in server_addr;
        server_addr.sin_family = AF_INET;
         server_addr.sin_port= htons(8080);
        server_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
        connect(client_socket, (struct sockaddr*)&server_addr,sizeof(server_addr));


    6. **发送数据 (`send()`)**:
       - 函数原型:`ssize_t send(int sockfd, constvoid *buf, size_t len, int flags);`
       - 用途:将数据从套接字发送到远程端点。
       - 参数:
         - `sockfd`:套接字描述符。
         - `buf`:要发送的数据的缓冲区。
         - `len`:要发送的数据的长度。
         - `flags`:标志位,通常设置为0。
       - 示例:
         char message[] ="Hello, server!";
        send(client_socket, message, strlen(message), 0);

    7. **接收数据 (`recv()`)**:
       - 函数原型:`ssize_t recv(int sockfd, void*buf, size_t len, int flags);`
       - 用途:从套接字接收数据。
       - 参数:
         - `sockfd`:套接字描述符。
         - `buf`:用于存储接收数据的缓冲区。
         - `len`:缓冲区的长度。
         - `flags`:标志位,通常设置为0。
       - 示例:
         charbuffer[1024];
         intbytes_received = recv(client_socket, buffer, sizeof(buffer), 0);

    8. **关闭套接字 (`close()`)**:
       - 函数原型:`int close(int sockfd);`
       - 用途:关闭套接字连接或释放套接字资源。
       - 参数:
         - `sockfd`:套接字描述符。
       - 示例:
        close(client_socket);
        close(server_socket);


    3.应用编程测试

    服务器端代码:
    #include<stdio.h>
    #include<stdlib.h>
    #include<string.h>
    #include<unistd.h>
    #include<arpa/inet.h>

    int main() {
        int server_socket, client_socket;
        struct sockaddr_in server_addr,client_addr;
        char buffer[1024];

        // 创建服务器套接字
        server_socket = socket(AF_INET,SOCK_STREAM, 0);
        if (server_socket == -1) {
            perror("Socket creationfailed");
            exit(1);
        }

        // 设置服务器地址和端口
        server_addr.sin_family = AF_INET;
        server_addr.sin_port = htons(8080);  // 使用8080端口
        server_addr.sin_addr.s_addr = INADDR_ANY;

        // 绑定套接字到地址和端口
        if (bind(server_socket, (structsockaddr*)&server_addr, sizeof(server_addr)) == -1) {
            perror("Binding failed");
            exit(1);
        }

        // 启动服务器监听
        if (listen(server_socket, 5) == -1) {
            perror("Listening failed");
            exit(1);
        }
       
        printf("Server listening on port8080...\n");

        socklen_t client_addr_len =sizeof(client_addr);

        // 接受客户端连接请求
        client_socket = accept(server_socket,(struct sockaddr*)&client_addr, &client_addr_len);
        if (client_socket == -1) {
            perror("Accepting connectionfailed");
            exit(1);
        }

        printf("Client connected.\n");

        // 接收客户端数据
        int bytes_received = recv(client_socket,buffer, sizeof(buffer), 0);
        if (bytes_received == -1) {
            perror("Receiving datafailed");
            exit(1);
        }
        buffer[bytes_received] = '\0';  // 添加字符串结束符

        printf("Received from client:%s\n", buffer);

        // 发送数据到客户端
        char message[] = "Hello,client!";
        int bytes_sent = send(client_socket,message, strlen(message), 0);
        if (bytes_sent == -1) {
            perror("Sending datafailed");
            exit(1);
        }

        // 关闭套接字连接
        close(client_socket);
        close(server_socket);

        return 0;
    }

    客户端代码:

    #include<stdio.h>
    #include<stdlib.h>
    #include<string.h>
    #include<unistd.h>
    #include<arpa/inet.h>

    int main() {
        int client_socket;
        struct sockaddr_in server_addr;
        char buffer[1024];

        // 创建套接字
        client_socket = socket(AF_INET,SOCK_STREAM, 0);
        if (client_socket == -1) {
            perror("Socket creationfailed");
            exit(1);
        }

        // 连接到服务器
        server_addr.sin_family = AF_INET;
        server_addr.sin_port = htons(8080);
        server_addr.sin_addr.s_addr = inet_addr("192.168.1.13");
       
        if (connect(client_socket, (structsockaddr*)&server_addr, sizeof(server_addr)) == -1) {
            perror("Connection failed");
            exit(1);
        }

        // 发送数据到服务器
        char message[] = "Hello,server!";
        int bytes_sent = send(client_socket, message,strlen(message), 0);
        if (bytes_sent == -1) {
            perror("Sending datafailed");
            exit(1);
        }

        // 接收服务器数据
        int bytes_received = recv(client_socket,buffer, sizeof(buffer), 0);
        if (bytes_received == -1) {
            perror("Receiving datafailed");
            exit(1);
        }
        buffer[bytes_received] = '\0';  // 添加字符串结束符

        printf("Received from server:%s\n", buffer);

        // 关闭套接字连接
        close(client_socket);

        return 0;
    }

    编译代码:

    输入以下命令编译代码:
    电脑运行客户端,开发板运行服务器端:
    arm-linux-gnueabihf-gcc-o server server.c
    gcc client.c -oclient
    1.png

    将编译的可执行文件传入开发板中,运行服务器端:

    2.png




    回复

    使用道具 举报

    您需要登录后才可以回帖 注册/登录

    本版积分规则

    关闭

    站长推荐上一条 /3 下一条

    手机版|小黑屋|与非网

    GMT+8, 2024-5-20 19:26 , Processed in 0.115607 second(s), 17 queries , MemCache On.

    ICP经营许可证 苏B2-20140176  苏ICP备14012660号-2   苏州灵动帧格网络科技有限公司 版权所有.

    苏公网安备 32059002001037号

    Powered by Discuz! X3.4

    Copyright © 2001-2024, Tencent Cloud.