#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <errno.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <termios.h>
#include <stdlib.h>
#include <pthread.h>
#include <sys/select.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#define ERRORLOG(msg) \
do \
{ \
printf("%s:%s:%d\n", __FILE__, __func__, __LINE__); \
perror(msg); \
} while (0);
#define BUFFER_SIZE 1024
#define FILEIDNAME "fileid.txt"
#define OUTDATADIR "data"
#define CLIENT_IP "192.168.1.3"
#define CLIENT_PORT 8000
#define BUFFER_SIZE 1024
int ReadLogFileId(void)
{
FILE *file;
int number = 0;
struct stat buffer;
// 检查文件是否存在
if (stat(FILEIDNAME, &buffer) != 0) // 不存在创建
{
char cmd[100] = {0};
sprintf(cmd, "echo 0 > %s", FILEIDNAME);
int ret = system(cmd);
if (ret != 0)
{
ERRORLOG("system error");
}
}
// 打开文件
file = fopen(FILEIDNAME, "r");
if (file == NULL)
{
ERRORLOG("open file error");
return -1;
}
// 读取数字
if (fscanf(file, "%d", &number) != 1)
{
ERRORLOG("read file id error");
fclose(file);
return -1;
}
if (number >= 50)
{
number = 0;
}
number += 1;
file = fopen(FILEIDNAME, "w");
if (file == NULL)
{
ERRORLOG("updata fileid error");
return -1;
}
else
{
fprintf(file, "%d", number);
}
// 关闭文件
fclose(file);
return number;
}
// 输出目录
void IfExistOutDataDir(void)
{
struct stat st = {0};
if (stat(OUTDATADIR, &st) == -1)
{
char cmd[100] = {0};
sprintf(cmd, "mkdir %s", OUTDATADIR);
system(cmd);
}
}
int set_opt(int fd, int nSpeed, int nBits, char nEvent, int nStop)
{
struct termios newtio, oldtio;
if (tcgetattr(fd, &oldtio) != 0)
{
perror("SetupSerial 1");
return -1;
}
bzero(&newtio, sizeof(newtio));
newtio.c_cflag |= CLOCAL | CREAD;
newtio.c_cflag = ~CSIZE;
switch (nBits)
{
case 7:
newtio.c_cflag |= CS7;
break;
case 8:
newtio.c_cflag |= CS8;
break;
}
switch (nEvent)
{
case 'O': // 奇校验
newtio.c_cflag |= PARENB;
newtio.c_cflag |= PARODD;
newtio.c_iflag |= (INPCK | ISTRIP);
break;
case 'E': // 偶校验
newtio.c_iflag |= (INPCK | ISTRIP);
newtio.c_cflag |= PARENB;
newtio.c_cflag = ~PARODD;
break;
case 'N': // 无校验
newtio.c_cflag = ~PARENB;
break;
}
switch (nSpeed)
{
case 300:
cfsetispeed(&newtio, B300);
cfsetospeed(&newtio, B300);
break;
case 600:
cfsetispeed(&newtio, B600);
cfsetospeed(&newtio, B600);
break;
case 1200:
cfsetispeed(&newtio, B1200);
cfsetospeed(&newtio, B1200);
break;
case 2400:
cfsetispeed(&newtio, B2400);
cfsetospeed(&newtio, B2400);
break;
case 4800:
cfsetispeed(&newtio, B4800);
cfsetospeed(&newtio, B4800);
break;
case 9600:
cfsetispeed(&newtio, B9600);
cfsetospeed(&newtio, B9600);
break;
case 19200:
cfsetispeed(&newtio, B19200);
cfsetospeed(&newtio, B19200);
break;
case 38400:
cfsetispeed(&newtio, B38400);
cfsetospeed(&newtio, B38400);
break;
case 57600:
cfsetispeed(&newtio, B57600);
cfsetospeed(&newtio, B57600);
break;
case 115200:
cfsetispeed(&newtio, B115200);
cfsetospeed(&newtio, B115200);
break;
default:
printf("sorry! [%d bps] is not support ,Set default 9600bps now!\n", nSpeed);
cfsetispeed(&newtio, B9600);
cfsetospeed(&newtio, B9600);
break;
}
if (nStop == 1)
{
newtio.c_cflag &= ~CSTOPB;
}
else if (nStop == 2)
{
newtio.c_cflag |= CSTOPB;
}
newtio.c_cc[VTIME] = 0;
newtio.c_cc[VMIN] = 0;
tcflush(fd, TCIFLUSH);
if ((tcsetattr(fd, TCSANOW, &newtio)) != 0)
{
perror("com set error");
return -1;
}
printf("uart init done!\n");
return 0;
}
int main(int argc, char **argv)
{
if (argc != 4)
{
printf("should inpurt [uartdev] [ip] [port]\n"); //./a.out /dev/ttyUSB0 192.168.1.3 6000
}
int fid = ReadLogFileId();
IfExistOutDataDir();
/**********************串口********************************************/
char output_file_name[256] = {0};
sprintf(output_file_name, "%s/%s%d%s", OUTDATADIR, "diff_data_", fid, ".txt");
FILE *fp;
if ((fp = fopen(output_file_name, "w+")) == NULL)
ERRORLOG("fopen error");
// char *serial_device = "/dev/ttyUSB0";
char *serial_device = argv[1];
int baudrate = 115200;
int serial_fd = open(serial_device, O_RDWR | O_NOCTTY | O_NDELAY);
if (serial_fd == -1)
{
ERRORLOG("Unable to open serial port");
return 1;
}
int setret = set_opt(serial_fd, baudrate, 8, 'N', 1);
if (setret == 0)
{
printf("open serial_device succesed !\n");
}
/*****************************网络配置********************************************************/
char output_file_name_net[256] = {0};
sprintf(output_file_name_net, "%s/%s%d%s", OUTDATADIR, "imu_data_", fid, ".txt");
FILE *fp1;
if ((fp1 = fopen(output_file_name_net, "w+")) == NULL)
ERRORLOG("fopen error");
int sockfd;
struct sockaddr_in server_addr, client_addr;
char buffer[BUFFER_SIZE];
socklen_t server_addr_size = sizeof(server_addr);
// 创建UDP套接字
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
if (sockfd == -1)
{
ERRORLOG("socket() error");
}
// 设置客户端地址结构
memset(&client_addr, 0, sizeof(client_addr));
client_addr.sin_family = AF_INET;
client_addr.sin_addr.s_addr = htonl(INADDR_ANY); // 接受任意IP
client_addr.sin_port = htons(CLIENT_PORT);
// 绑定套接字到客户端地址
if (bind(sockfd, (struct sockaddr *)&client_addr, sizeof(client_addr)) == -1)
{
ERRORLOG("bind() error");
}
printf("UDP Client is running. Waiting for messages...\n");
fd_set read_fds;
int max_fd = (sockfd > serial_fd) ? sockfd : serial_fd;
char readBuffer[BUFFER_SIZE] = {0}; // 用于每次存储读取的数据
char readBuffer_net[BUFFER_SIZE] = {0}; // 用于每次存储读取的数据
int uart_bytes = 0;
int net_bytes = 0;
int flag = 1;
while (1)
{
// if (flag == 1)
// {
// // 连上后给服务器发送消息,使服务端保存客户端网络信息便于回复
// if (-1 == sendto(sockfd, "hello", 6, 0, (struct sockaddr *)&client_addr, server_addr_size))
// {
// ERRORLOG("send error");
// }
// flag = 0;
// }
FD_ZERO(&read_fds);
FD_SET(sockfd, &read_fds); // 添加 TCP 套接字
FD_SET(serial_fd, &read_fds); // 添加串口
// 使用 select 等待数据
int activity = select(max_fd + 1, &read_fds, NULL, NULL, NULL);
if (activity < 0)
{
ERRORLOG("select error");
break;
}
// 检查串口是否可读
if (FD_ISSET(serial_fd, &read_fds))
{
uart_bytes = read(serial_fd, readBuffer, sizeof(readBuffer));
if (uart_bytes > 0)
{
size_t write_count = fwrite(readBuffer, 1, uart_bytes, fp);
if (write_count < uart_bytes)
{
ERRORLOG("fwrite error");
}
fflush(fp); // 刷新文件缓冲区
memset(readBuffer, 0, sizeof(readBuffer));
uart_bytes = 0;
}
}
// 检查 UDP 套接字是否可读
if (FD_ISSET(sockfd, &read_fds))
{
// 接收应答消息 无需再次保存服务器的网络信息结构体了
// 因为我们的 serveraddr 一直没动过
net_bytes = recvfrom(sockfd, readBuffer_net, sizeof(readBuffer_net), 0, NULL, NULL);
if (net_bytes == -1)
{
ERRORLOG("recv error");
}
printf("%s\n", readBuffer_net);
if (net_bytes > 0)
{
size_t write_count = fwrite(readBuffer_net, 1, net_bytes, fp1);
if (write_count < net_bytes)
{
ERRORLOG("fwrite error");
}
fflush(fp1); // 刷新文件缓冲区
memset(readBuffer_net, 0, sizeof(readBuffer_net));
net_bytes = 0;
}
else
{
printf("UDP 连接关闭。\n");
break;
}
}
}
return 0;
}
另附udp网络编程:
说明:两台主机(客户端和服务端在同一网段,服务端ip:192.168.1.2:6000,客户端192.168.1.3:8000),服务端向指定客户端的ip和端口发送数据:
udpserver.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#define SERVER_IP "192.168.1.2"
#define SERVER_PORT 6000
#define CLIENT_IP "192.168.1.3"
#define CLIENT_PORT 8000
#define BUFFER_SIZE 1024
void error_handling(char *message);
int main(int argc, char *argv[]) {
int sock;
struct sockaddr_in server_addr, client_addr;
char message[BUFFER_SIZE];
socklen_t client_addr_size = sizeof(client_addr);
// 创建UDP套接字
sock = socket(PF_INET, SOCK_DGRAM, 0);
if (sock == -1) {
error_handling("socket() error");
}
// 设置服务端地址结构
memset(&server_addr, 0, sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = inet_addr(SERVER_IP);
server_addr.sin_port = htons(SERVER_PORT);
// 绑定套接字到服务端地址
if (bind(sock, (struct sockaddr*)&server_addr, sizeof(server_addr)) == -1) {
error_handling("bind() error");
}
// 设置客户端地址结构
memset(&client_addr, 0, sizeof(client_addr));
client_addr.sin_family = AF_INET;
client_addr.sin_addr.s_addr = inet_addr(CLIENT_IP);
client_addr.sin_port = htons(CLIENT_PORT);
while (1) {
printf("Input message to send: ");
fflush(stdout); // 清空stdout缓冲区,确保立即打印提示信息
fgets(message, BUFFER_SIZE, stdin); // 从标准输入读取消息
// 发送消息到客户端
if (sendto(sock, message, strlen(message), 0, (struct sockaddr*)&client_addr, client_addr_size) == -1) {
error_handling("sendto() error");
}
}
close(sock);
return 0;
}
void error_handling(char *message) {
fputs(message, stderr);
fputc('\n', stderr);
exit(1);
}
client.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#define CLIENT_IP "192.168.1.3"
#define CLIENT_PORT 8000
#define BUFFER_SIZE 1024
void error_handling(char *message);
int main(int argc, char *argv[]) {
int sock;
struct sockaddr_in server_addr, client_addr;
char buffer[BUFFER_SIZE];
socklen_t server_addr_size = sizeof(server_addr);
// 创建UDP套接字
sock = socket(AF_INET, SOCK_DGRAM, 0);
if (sock == -1) {
error_handling("socket() error");
}
// 设置客户端地址结构
memset(&client_addr, 0, sizeof(client_addr));
client_addr.sin_family = AF_INET;
client_addr.sin_addr.s_addr = htonl(INADDR_ANY); // 接受任意IP
client_addr.sin_port = htons(CLIENT_PORT);
// 绑定套接字到客户端地址
if (bind(sock, (struct sockaddr*)&client_addr, sizeof(client_addr)) == -1) {
error_handling("bind() error");
}
printf("UDP Client is running. Waiting for messages...\n");
while (1) {
// 接收来自服务端的消息
int str_len = recvfrom(sock, buffer, BUFFER_SIZE, 0, (struct sockaddr*)&server_addr, &server_addr_size);
if (str_len == -1) {
error_handling("recvfrom() error");
}
buffer[str_len] = '\0'; // 确保字符串以NULL结尾
printf("Message received: %s\n", buffer);
}
close(sock);
return 0;
}
void error_handling(char *message) {
fputs(message, stderr);
fputc('\n', stderr);
exit(1);
}