EMS/drv/drv_tcp.c

183 lines
5.6 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "drv_tcp.h"
#define BUFFER_SIZE 1024
void getInterfacesAndIPs(char *interfaces[], char *ips[], int *count) {
struct ifconf ifc;
struct ifreq *ifr;
int sockfd;
char buffer[BUFFER_SIZE];
char ipAddress[INET_ADDRSTRLEN];
// 创建套接字
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
if (sockfd < 0) {
perror("创建套接字失败");
return;
}
ifc.ifc_buf = buffer;
ifc.ifc_len = sizeof(buffer);
// 获取网络接口配置信息
if (ioctl(sockfd, SIOCGIFCONF, &ifc) < 0) {
perror("获取网络接口配置失败");
close(sockfd);
return;
}
ifr = (struct ifreq *)ifc.ifc_buf;
int numInterfaces = ifc.ifc_len / sizeof(struct ifreq);
*count = numInterfaces;
for (int i = 0; i < numInterfaces; i++) {
printf("网口名字: %s\n", ifr[i].ifr_name);
interfaces[i] = strdup(ifr[i].ifr_name);
// 获取IP地址
if (ioctl(sockfd, SIOCGIFADDR, &ifr[i]) < 0) {
perror("获取IP地址失败");
} else {
struct sockaddr_in *addr = (struct sockaddr_in *)&ifr[i].ifr_addr;
inet_ntop(AF_INET, &addr->sin_addr, ipAddress, INET_ADDRSTRLEN);
printf("IP地址: %s\n", ipAddress);
ips[i] = strdup(ipAddress);
}
}
close(sockfd);
}
// 关闭与某个网口相关的套接字并释放内存
void closeAndFree(int server_fd, int new_socket, char *interface, char *ip) {
close(new_socket);
close(server_fd);
free(interface);
if (ip!= NULL) {
free(ip);
}
}
// 线程函数,用于处理每个网口的监听和连接
void *tcpServeThread(void *arg) {
int port = 8888;
int server_fd, new_socket;
struct sockaddr_in address;
int addrlen = sizeof(address);
char buffer[BUFFER_SIZE];
char *interface = ((char **)arg)[0];
char *ip = ((char **)arg)[1];
int optval = 1;
// printf("Port : %d", port);
// 创建套接字
label:
if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0) {
perror("套接字创建失败");
pthread_exit(NULL);
}
if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval)) < 0) {
perror("设置套接字选项失败");
close(server_fd);
exit(EXIT_FAILURE);
}
printf("设置套接字选项成功\n");
// 设置服务器地址结构体
address.sin_family = AF_INET;
inet_pton(AF_INET, ip, &address.sin_addr);
address.sin_port = htons(port);
// 绑定套接字到指定地址和端口
if (bind(server_fd, (struct sockaddr *)&address, sizeof(address)) < 0) {
perror("绑定失败");
closeAndFree(server_fd, -1, interface, ip);
pthread_exit(NULL);
}
// 监听端口,等待客户端连接
if (listen(server_fd, 3) < 0) {
perror("监听失败");
closeAndFree(server_fd, -1, interface, ip);
pthread_exit(NULL);
}
printf("在端口 %sIP: %s端口%d上启动服务器正在等待客户端连接...\n", interface, ip, port);
// 接受客户端连接
if ((new_socket = accept(server_fd, (struct sockaddr *)&address, (socklen_t *)&addrlen)) < 0) {
perror("接受连接失败");
closeAndFree(server_fd, -1, interface, ip);
pthread_exit(NULL);
}
printf("客户端已连接到网口 %sIP: %s\n", interface, ip);
char client_ip[INET_ADDRSTRLEN];
inet_ntop(AF_INET, &(address.sin_addr), client_ip, INET_ADDRSTRLEN);
printf("Client IP: %s\n", client_ip);
while (1) {
// 接收客户端发送的数据
memset(buffer, 0, BUFFER_SIZE);
if (recv(new_socket, buffer, BUFFER_SIZE, 0) < 0) {
perror("接收数据失败");
break;
}
if (strlen(buffer) == 0) {
// 客户端断开连接
printf("客户端已断开连接,从网口 %sIP: %s断开。\n", interface, ip);
close(new_socket);
close(server_fd);
sleep(1);
goto label;
}
printf("端口%s,ip:%s,端口号:%d,收到客户端消息:%s\n", interface, ip, port, buffer);
// 向客户端发送相同的数据作为回复
if (send(new_socket, buffer, strlen(buffer), 0) < 0) {
perror("发送数据失败");
break;
}
}
// 关闭与该网口相关的套接字并释放内存
closeAndFree(server_fd, new_socket, interface, ip);
pthread_exit(NULL);
}
void tcpServe(int port) {
char *interfaces[100];
char *ips[100];
int numInterfaces;
// 获取本地所有网口名称及对应的IP地址
getInterfacesAndIPs(interfaces, ips, &numInterfaces);
pthread_t threads[100];
char * thread_args[100][3];
for (int i = 0; i < numInterfaces; i++) {
if (ips[i] == NULL) {
continue;
}
// char * portChar;
// sprintf(portChar, "%d", port);
// 为每个线程准备参数
// thread_args[i][0] = portChar;
thread_args[i][0] = interfaces[i];
thread_args[i][1] = ips[i];
// 创建线程
if (pthread_create(&threads[i], NULL, tcpServeThread, &thread_args[i])!= 0) {
perror("线程创建失败");
closeAndFree(-1, -1, interfaces[i], ips[i]);
continue;
}
}
// 等待所有线程完成
for (int i = 0; i < numInterfaces; i++) {
if (threads[i]!= 0) {
pthread_join(threads[i], NULL);
}
}
}