回答

收藏

[评测分享] 【更适合初学者的开发板ELF 1】+ 8.网络编程

#板卡评测 #板卡评测 1895 人阅读 | 0 人回复 | 2023-12-17

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,由系统自动选择合适的协议。
   - 示例:
     ```c
     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` 结构的长度。
   - 示例:
     ```c
     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`:等待连接队列的最大长度,指定同时能处理多少个等待连接的客户端。
   - 示例:
     ```c
    listen(server_socket, 5);  // 允许最多5个等待连接的客户端
     ```
4. **接受客户端连接请求 (`accept()`)**:
   - 函数原型:`int accept(int sockfd, structsockaddr *addr, socklen_t *addrlen);`
   - 用途:仅用于服务器套接字,用于接受客户端的连接请求,返回一个新的套接字描述符,用于与客户端通信。
   - 参数:
     - `sockfd`:服务器套接字描述符。
     - `addr`:一个 `struct sockaddr` 结构,用于存储客户端的地址信息。
     - `addrlen`:`addr` 结构的长度。
   - 示例:
     ```c
     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` 结构的长度。
   - 示例:
     ```c
     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。
   - 示例:
     ```c
     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。
   - 示例:
     ```c
     charbuffer[1024];
     intbytes_received = recv(client_socket, buffer, sizeof(buffer), 0);
     ```
8. **关闭套接字 (`close()`)**:
   - 函数原型:`int close(int sockfd);`
   - 用途:关闭套接字连接或释放套接字资源。
   - 参数:
     - `sockfd`:套接字描述符。
   - 示例:
     ```c
    close(client_socket);
     close(server_socket);
     ```
3.应用编程测试
服务器端:
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <unistd.h>
  5. #include <arpa/inet.h>

  6. int main() {
  7.     int server_socket, client_socket;
  8.     struct sockaddr_in server_addr, client_addr;
  9.     char buffer[1024];

  10.     // 创建服务器套接字
  11.     server_socket = socket(AF_INET, SOCK_STREAM, 0);
  12.     if (server_socket == -1) {
  13.         perror("Socket creation failed");
  14.         exit(1);
  15.     }

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

  20.     // 绑定套接字到地址和端口
  21.     if (bind(server_socket, (struct sockaddr*)&server_addr, sizeof(server_addr)) == -1) {
  22.         perror("Binding failed");
  23.         exit(1);
  24.     }

  25.     // 启动服务器监听
  26.     if (listen(server_socket, 5) == -1) {
  27.         perror("Listening failed");
  28.         exit(1);
  29.     }
  30.    
  31.     printf("Server listening on port 8080...\n");

  32.     socklen_t client_addr_len = sizeof(client_addr);

  33.     // 接受客户端连接请求
  34.     client_socket = accept(server_socket, (struct sockaddr*)&client_addr, &client_addr_len);
  35.     if (client_socket == -1) {
  36.         perror("Accepting connection failed");
  37.         exit(1);
  38.     }

  39.     printf("Client connected.\n");

  40.     // 接收客户端数据
  41.     int bytes_received = recv(client_socket, buffer, sizeof(buffer), 0);
  42.     if (bytes_received == -1) {
  43.         perror("Receiving data failed");
  44.         exit(1);
  45.     }
  46.     buffer[bytes_received] = '\0';  // 添加字符串结束符

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

  48.     // 发送数据到客户端
  49.     char message[] = "Hello, client!";
  50.     int bytes_sent = send(client_socket, message, strlen(message), 0);
  51.     if (bytes_sent == -1) {
  52.         perror("Sending data failed");
  53.         exit(1);
  54.     }

  55.     // 关闭套接字连接
  56.     close(client_socket);
  57.     close(server_socket);

  58.     return 0;
  59. }
复制代码
客户端:
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <unistd.h>
  5. #include <arpa/inet.h>

  6. int main() {
  7.     int client_socket;
  8.     struct sockaddr_in server_addr;
  9.     char buffer[1024];

  10.     // 创建套接字
  11.     client_socket = socket(AF_INET, SOCK_STREAM, 0);
  12.     if (client_socket == -1) {
  13.         perror("Socket creation failed");
  14.         exit(1);
  15.     }

  16.     // 连接到服务器
  17.     server_addr.sin_family = AF_INET;
  18.     server_addr.sin_port = htons(8080);
  19.     server_addr.sin_addr.s_addr = inet_addr("192.168.31.111");
  20.    
  21.     if (connect(client_socket, (struct sockaddr*)&server_addr, sizeof(server_addr)) == -1) {
  22.         perror("Connection failed");
  23.         exit(1);
  24.     }

  25.     // 发送数据到服务器
  26.     char message[] = "Hello, server!";
  27.     int bytes_sent = send(client_socket, message, strlen(message), 0);
  28.     if (bytes_sent == -1) {
  29.         perror("Sending data failed");
  30.         exit(1);
  31.     }

  32.     // 接收服务器数据
  33.     int bytes_received = recv(client_socket, buffer, sizeof(buffer), 0);
  34.     if (bytes_received == -1) {
  35.         perror("Receiving data failed");
  36.         exit(1);
  37.     }
  38.     buffer[bytes_received] = '\0';  // 添加字符串结束符

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

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

  42.     return 0;
  43. }
复制代码
4.验证
编译客服端和用户端到开发板:

客服端验证,将可执行文件拖入开发板,添加可执行权限,并运行客服端:

打开网络调试助手,配置相关信息:
连接网络并发送数据:

分享到:
回复

使用道具 举报

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

本版积分规则

1326 积分
16 主题
+ 关注
热门推荐
关闭

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