大概流程就是:main.c 主文件运行后,接受客户端连接,当客户端发相应命令过来后,在tcp.c 文件中解析后,调用function.c文件中的处理函数:Receive_Process()。 void Receive_Process(int conn_fd,unsigned char* buff_r,unsigned char* buff_w) 如果这样的话,就没这些问题了,处理的结果,我在tcp.c文件中,通过 “unsigned char* buff_w” 可以拿到,送给PC就完事了。 现在同事要求不这么干,即不通过Receive_Process()进、出方式,把结果返回。而是要在fuction.c中(当然也可能其他文件中可以调用发送函数,把结果送给PC)把结果直接送给PC端… (在另个帖子里可能没描述清楚) 主文件: #include "tcp.h" int main(int argc, char * argv[]) { tcp_initialize(); epoll_fd_tcp=create_epoll_tcp(MAX_EVENTS_TCP); while(1) { do_process_tcp_nowhile(); sleep(1); } } 处理文件:function.c #include "function.h" void Receive_Process(int conn_fd,unsigned char* buff_r,unsigned char* buff_w) { unsigned char CmdKey; unsigned char length; int len,i; len = buff_r[1]; CmdKey = buff_r[2]; printf("packet len is : %02X\n",buff_r[1]); printf("cmdkey is : %02X\n",buff_r[2]); for(i=0;i<len;i++) buff_r[i]=buff_r[i+1]; for(i=0;i<len;i++) printf("%02X ",buff_r[i]); printf("\n"); switch(CmdKey) { case 0x02: //write_spi_arm_to_fpga_array(5,buff_r,buff_w); // 根据命令,与FPGA交互后,将返回结果送给PC端,下面是模拟的数据。 buff_w[0]=0x08; buff_w[1]=0x03; buff_w[2]=0x8c; buff_w[3]=0x00; buff_w[4]=0x00; //send to pc tcp_send_data_to_pc(5 buff_w); // 无发完成发送任务,这个函数只能在tcp.c文件中能正常,出了tcp.c文件就不行了。 printf("CMD_GET_VERSION OK \n"); break; default: break; } } TCP文件: tcp.c #include "tcp.h" 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]; // 数据传送的缓冲区 unsigned char retn_data_buffer_size_tcp[BUFFER_SIZE_TCP]; int m=0; int len; //设置句柄为非阻塞方式 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,4,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"); } 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 {//处理PC来的命令包,,调用fuction.c文件中的 Receive_Process()函数 Receive_Process(4,send_data_buffer_size_tcp,retn_data_buffer_size_tcp); 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); //这个地方就正常 } } if(server_sock_fd_tcp>0) { printf("socket close \n"); shutdown(server_sock_fd_tcp,SHUT_RDWR); close(server_sock_fd_tcp); } } tcp.h头文件 #include <arpa/inet.h> #include <fcntl.h> #include <sys/epoll.h> #include <sys/time.h> #include <sys/resource.h> #define BUFFER_SIZE_TCP 40 #define MAX_EVENTS_TCP 10 #define HOST_IP_ADDRESS_TCP "192.168.1.200" #define HOST_PORT_TCP 4530 int n; struct epoll_event ev;// epoll事件结构体 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_nowhile(); |
|
来个人顶一下呀
也好结贴 呢 结贴,还能赚个50 嘿嘿 |
|
10分 |
好奇为何不直接用libevent呢?
|
90分 |
实现不好意思回这个贴了
上两次回贴都没帮到你。 发送数据跟 epoll 是没有关系的. 都可以直接 write(fd ,….) Receive_Process(4,send_data_buffer_size_tcp …) 下面的 所有关于EPOLLOUT 事件注册和处理都不要了 // ————————————— |
上次帮到了 呵呵 |