嵌入式 Linux TCP Socket
在嵌入式系统中,TCP socket 编程是一种常见的通信方式。它允许嵌入式设备通过网络进行数据传输,这对于物联网(IoT)设备特别重要。本篇博客将详细介绍如何在嵌入式 Linux 环境中进行 TCP socket 编程。
前置知识
在开始编程之前,需要具备以下知识:
- C 语言编程基础
- 基本的网络协议知识,特别是 TCP/IP 协议
- Linux 操作系统基础
创建 TCP Socket
在嵌入式 Linux 中创建 TCP socket 的基本步骤如下:
-
包含头文件
#include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <unistd.h> #include <stdio.h> #include <stdlib.h> #include <string.h>
-
创建 socket
int sockfd = socket(AF_INET, SOCK_STREAM, 0); if (sockfd < 0) { perror("socket creation failed"); exit(EXIT_FAILURE); }
AF_INET
表示使用 IPv4 地址,SOCK_STREAM
表示使用 TCP 协议。 -
绑定地址
struct sockaddr_in servaddr; memset(&servaddr, 0, sizeof(servaddr)); servaddr.sin_family = AF_INET; servaddr.sin_addr.s_addr = INADDR_ANY; servaddr.sin_port = htons(8080); if (bind(sockfd, (const struct sockaddr *)&servaddr, sizeof(servaddr)) < 0) { perror("bind failed"); close(sockfd); exit(EXIT_FAILURE); }
INADDR_ANY
表示绑定到所有可用的接口,htons(8080)
将端口号转换为网络字节序。 -
监听连接
if (listen(sockfd, 5) < 0) { perror("listen failed"); close(sockfd); exit(EXIT_FAILURE); }
5
表示允许队列中最多有 5 个待处理连接。 -
接受连接
struct sockaddr_in cliaddr; socklen_t len = sizeof(cliaddr); int newsockfd = accept(sockfd, (struct sockaddr *)&cliaddr, &len); if (newsockfd < 0) { perror("server accept failed"); close(sockfd); exit(EXIT_FAILURE); }
-
数据传输
char buffer[1024]; int n; // 接收数据 n = read(newsockfd, buffer, sizeof(buffer)); if (n < 0) { perror("read failed"); } buffer[n] = '\0'; printf("Client: %s\n", buffer); // 发送数据 strcpy(buffer, "Hello from server"); n = write(newsockfd, buffer, strlen(buffer)); if (n < 0) { perror("write failed"); }
-
关闭 socket
close(newsockfd); close(sockfd);
完整代码示例
以下是一个完整的 TCP 服务器代码示例:
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main() {
int sockfd, newsockfd;
struct sockaddr_in servaddr, cliaddr;
socklen_t len;
char buffer[1024];
int n;
// 创建 socket
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0) {
perror("socket creation failed");
exit(EXIT_FAILURE);
}
// 绑定地址
memset(&servaddr, 0, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = INADDR_ANY;
servaddr.sin_port = htons(8080);
if (bind(sockfd, (const struct sockaddr *)&servaddr, sizeof(servaddr)) < 0) {
perror("bind failed");
close(sockfd);
exit(EXIT_FAILURE);
}
// 监听连接
if (listen(sockfd, 5) < 0) {
perror("listen failed");
close(sockfd);
exit(EXIT_FAILURE);
}
// 接受连接
len = sizeof(cliaddr);
newsockfd = accept(sockfd, (struct sockaddr *)&cliaddr, &len);
if (newsockfd < 0) {
perror("server accept failed");
close(sockfd);
exit(EXIT_FAILURE);
}
// 数据传输
n = read(newsockfd, buffer, sizeof(buffer));
if (n < 0) {
perror("read failed");
}
buffer[n] = '\0';
printf("Client: %s\n", buffer);
strcpy(buffer, "Hello from server");
n = write(newsockfd, buffer, strlen(buffer));
if (n < 0) {
perror("write failed");
}
// 关闭 socket
close(newsockfd);
close(sockfd);
return 0;
}