EPOLL 方式的 TCP 怎么封装一个发送函数,任意文件中可以定义
EPOLL 方式的 TCP 如何封装一个发送函数,任意文件中可以定义?
网上找的代码,简单组织了下,发现发送函数,不能在主文件中调用,不能成功把临时加的值给发送给PC
后来发现是 “n” 变量这个值的问题,下面是在控制台上 打印 变量 n 的值结果:
请教这代码如何修改,才能封装一个函数,可以在任何文件中都可以调用?而且可以保证多个客户端 同时可以连接上来,且返回给每个客户端的数据正确(每个客户端发送内容可能不一样)
tcp相关代码:
头文件
------解决思路----------------------
估计得用宏来实现了。
------解决思路----------------------
不清楚楼主具体send不出数据是什么情况
但代码有些问题
// ev.events=EPOLLIN
------解决思路----------------------
EPOLLET;
注册epoll 的 event 用的是 EPOLLET 边缘触发 模式。
但不管是accept, recv 还是send 等处理的方式却 LT 模式
// =======================================
很长时间没裸写 epoll 了, 详细情况我也说不清。
不了解 epoll 情况下, 个人不推荐祼写..
网上找的代码,简单组织了下,发现发送函数,不能在主文件中调用,不能成功把临时加的值给发送给PC
后来发现是 “n” 变量这个值的问题,下面是在控制台上 打印 变量 n 的值结果:
in while n == 1
epoll nfds_tcp = 1
for loop epoll nfds_tcp = 1
in while n == 0
in while n == 0
n == 0
// 到主函数里后, 再次调用发送函数时,“n” 变量值改变了...
in while n == 1
请教这代码如何修改,才能封装一个函数,可以在任何文件中都可以调用?而且可以保证多个客户端 同时可以连接上来,且返回给每个客户端的数据正确(每个客户端发送内容可能不一样)
#include "tcp.h"
int main(int argc, char * argv[])
{
unsigned char send_data_buffer_size[4];
send_data_buffer_size[0]=0xAA;
send_data_buffer_size[1]=0xAA;
send_data_buffer_size[2]=0xAA;
send_data_buffer_size[3]=0xAA;
tcp_initialize();
epoll_fd_tcp=create_epoll_tcp(MAX_EVENTS_TCP);
while(1)
{
do_process_tcp_nowhile();
sleep(1);
set_tcp_event_out();
tcp_send_data_to_pc(4,send_data_buffer_size);
}
}
tcp相关代码:
#include "tcp.h"
//int n=0; // 移动到tcp.h
struct epoll_event ev;// epoll事件结构体
struct epoll_event events[MAX_EVENTS_TCP];// 事件监听队列
int server_sock_fd_tcp;// 服务器端套接字
int client_sock_fd_tcp;// 客户端套接字
int nfds_tcp;// epoll监听事件发生的个数
int len_recv_data_tcp;
struct sockaddr_in host_addr_tcp; // 服务器网络地址结构体
struct sockaddr_in remote_addr_tcp; // 客户端网络地址结构体
int sin_size;
unsigned char send_data_buffer_size_tcp[BUFFER_SIZE_TCP]; // 数据传送的缓冲区
int m=0;
//设置句柄为非阻塞方式
int setnonblocking(int sockfd)
{
if (fcntl(sockfd, F_SETFL, fcntl(sockfd, F_GETFD, 0)|O_NONBLOCK) == -1)
{
return -1;
}
return 0;
}
int tcp_send_data_to_pc(int len,char* buffer)
{
printf("in while n == %d \n",n);
send(events[n].data.fd,buffer,8,0);
ev.events = EPOLLIN;
ev.data.fd = events[n].data.fd;
epoll_ctl(epoll_fd_tcp, EPOLL_CTL_MOD, ev.data.fd, &ev);
}
void tcp_initialize()
{
struct rlimit rt;
/* 设置每个进程允许打开的最大文件数 */
rt.rlim_max = rt.rlim_cur = 1024;
if (setrlimit(RLIMIT_NOFILE, &rt) == -1)
{
perror("setrlimit");
exit(1);
}
else
{
printf("setrlimit ok! \n");
}
// 创建服务器端套接字--IPv4协议,面向连接通信,TCP协议
if((server_sock_fd_tcp=socket(PF_INET,SOCK_STREAM,0))<0)
{
perror("socket");
//return 1;
}
else
{
printf("Tcp server socket ok...\n");
}
// 设置 socket属性,端口可以重用
int opt=SO_REUSEADDR;
setsockopt(server_sock_fd_tcp,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(opt));
setnonblocking(server_sock_fd_tcp);
memset(&host_addr_tcp,0,sizeof(host_addr_tcp)); // 数据初始化--清零
host_addr_tcp.sin_family=PF_INET; // 设置为IP通信
host_addr_tcp.sin_addr.s_addr=inet_addr(HOST_IP_ADDRESS_TCP);// 服务器IP地址--允许连接到所有本地地址上
host_addr_tcp.sin_port=htons(HOST_PORT_TCP); // 服务器端口号
// 将套接字绑定到服务器的网络地址上
if (bind(server_sock_fd_tcp,(struct sockaddr *)&host_addr_tcp,sizeof(struct sockaddr))<0)
{
perror("bind");
//return 1;
}
else
{
printf("Tcp server bind ok...\n");
printf("IP : %s \n", inet_ntoa(host_addr_tcp.sin_addr));
printf("port: %d \n",ntohs(host_addr_tcp.sin_port));
}
// 监听连接请求--监听队列长度为5
listen(server_sock_fd_tcp,64);
sin_size=sizeof(struct sockaddr_in);
}
// 创建一个epoll句柄
int create_epoll_tcp(unsigned int event_num)
{
int epoll_fd;
epoll_fd=epoll_create(event_num);
if(epoll_fd==-1)
{
perror("epoll_create failed");
}
ev.events=EPOLLIN | EPOLLET;
ev.data.fd=server_sock_fd_tcp;
// 向epoll注册server_sockfd监听事件
if(epoll_ctl(epoll_fd,EPOLL_CTL_ADD,server_sock_fd_tcp,&ev)==-1)
{
perror("epll_ctl:server_sock_fd_tcp register failed");
}
else
{
printf("socket adding in epoll success! \n");
}
return epoll_fd;
}
void do_process_tcp_nowhile()
{
// 等待事件发生
nfds_tcp=epoll_wait(epoll_fd_tcp,events,1024,-1);
if(nfds_tcp==-1)
{
perror("start epoll_wait failed");
//exit(EXIT_FAILURE);
}
else
{
printf(" epoll nfds_tcp = %d \n",nfds_tcp);
}
for(n=0;n<nfds_tcp;++n)
{
printf(" for loop epoll nfds_tcp = %d \n",nfds_tcp);
// 客户端有新的连接请求
if(events[n].data.fd == server_sock_fd_tcp)
{
// 等待客户端连接请求到达
if((client_sock_fd_tcp=accept(server_sock_fd_tcp,(struct sockaddr *)&remote_addr_tcp,&sin_size))<0)
{
perror("accept client_sock_fd_tcp failed");
exit(EXIT_FAILURE);
}
// 向epoll注册client_sockfd监听事件
setnonblocking(client_sock_fd_tcp);
ev.events=EPOLLIN | EPOLLET;
ev.data.fd=client_sock_fd_tcp;
if(epoll_ctl(epoll_fd_tcp,EPOLL_CTL_ADD,client_sock_fd_tcp,&ev)==-1)
{
perror("epoll_ctl:client_sock_fd_tcp register failed");
//exit(EXIT_FAILURE);
}
printf("accept client %s\n",inet_ntoa(remote_addr_tcp.sin_addr));
}
else if(events[n].events & EPOLLIN)
{
// 客户端有数据发送过来
sprintf(send_data_buffer_size_tcp,"");
//sin_size=sizeof(remote_addr_tcp);
len_recv_data_tcp=recv(events[n].data.fd,send_data_buffer_size_tcp,BUFFER_SIZE_TCP,0);
if(len_recv_data_tcp<=0)
{
printf("close id is : %d \n",events[n].data.fd);
if(epoll_ctl(epoll_fd_tcp,EPOLL_CTL_DEL,events[n].data.fd,&ev)==0)
{
printf("delete ok \n");
close(events[n].data.fd);
}
else
{
printf("delete error \n");
}
}
else
{
printf("current recv fd is : %d \n",events[n].data.fd);
printf("recv data: %d\n ",len_recv_data_tcp);
for(m=0;m<4;m++)
printf(" %02X",send_data_buffer_size_tcp[m]);
printf("\n");
printf("\n");
ev.data.fd = events[n].data.fd;
ev.events = EPOLLOUT|EPOLLET;
epoll_ctl(epoll_fd_tcp, EPOLL_CTL_MOD, events[n].data.fd, &ev);
}
}
else if(events[n].events & EPOLLOUT)//发送
{
tcp_send_data_to_pc(4,send_data_buffer_size_tcp);
tcp_send_data_to_pc(4,send_data_buffer_size_tcp);
printf(" n == %d \n",n);
}
}
if(server_sock_fd_tcp>0)
{
printf("socket close \n");
shutdown(server_sock_fd_tcp,SHUT_RDWR);
close(server_sock_fd_tcp);
}
}
头文件
#define BUFFER_SIZE_TCP 40
#define MAX_EVENTS_TCP 10
#define HOST_IP_ADDRESS_TCP "192.168.1.102"
#define HOST_PORT_TCP 4530
int n;
int epoll_fd_tcp;
int tcp_send_data_to_pc(int len,char* buffer);
void tcp_initialize();
int create_epoll_tcp(unsigned int event_num);
void do_process_tcp();
void do_process_tcp_nowhile();
void set_tcp_event_out();
------解决思路----------------------
估计得用宏来实现了。
------解决思路----------------------
不清楚楼主具体send不出数据是什么情况
但代码有些问题
int tcp_send_data_to_pc(int len,char* buffer)
{
printf("in while n == %d \n",n);
send(events[n].data.fd,buffer,8,0); // 这个 8 ???// 应该是参数 len 吧
ev.events = EPOLLIN;
ev.data.fd = events[n].data.fd;
epoll_ctl(epoll_fd_tcp, EPOLL_CTL_MOD, ev.data.fd, &ev);
}
// ...
// 这个 buffer 不管recv 还是 send 都是它。且而还是共用的这样设计问题
unsigned char send_data_buffer_size_tcp[BUFFER_SIZE_TCP];
// ev.events=EPOLLIN
------解决思路----------------------
EPOLLET;
注册epoll 的 event 用的是 EPOLLET 边缘触发 模式。
但不管是accept, recv 还是send 等处理的方式却 LT 模式
// =======================================
很长时间没裸写 epoll 了, 详细情况我也说不清。
不了解 epoll 情况下, 个人不推荐祼写..