免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 2643 | 回复: 5
打印 上一主题 下一主题

[C] EPOLL 方式的 TCP 如何封装一个发送函数,任意文件中可以定义? [复制链接]

论坛徽章:
1
2015年辞旧岁徽章
日期:2015-03-03 16:54:15
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2015-04-17 14:30 |只看该作者 |倒序浏览
5可用积分

网上找的代码,简单组织了下,发现发送函数,不能在主文件中调用,不能成功把临时加的值给发送给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



请教这代码如何修改,才能封装一个函数,可以在任何文件中都可以调用?而且可以保证多个客户端 同时可以连接上来,且返回给每个客户端的数据正确(每个客户端发送内容可能不一样)


主文件:
[code]

#include "tcp.h"
int main(int argc, char * argv[])   
{

论坛徽章:
1
2015年辞旧岁徽章
日期:2015-03-03 16:54:15
2 [报告]
发表于 2015-04-17 14:58 |只看该作者


  1. #include "tcp.h"
  2. int main(int argc, char * argv[])   
  3. {
  4.         unsigned char send_data_buffer_size[4];
  5.         send_data_buffer_size[0]=0xAA;
  6.         send_data_buffer_size[1]=0xAA;
  7.         send_data_buffer_size[2]=0xAA;
  8.         send_data_buffer_size[3]=0xAA;
  9.        
  10.                 tcp_initialize();
  11.                 epoll_fd_tcp=create_epoll_tcp(MAX_EVENTS_TCP);         
  12.           while(1)
  13.           {
  14.                    do_process_tcp_nowhile();
  15.                    sleep(1);
  16.                    set_tcp_event_out();
  17.                    tcp_send_data_to_pc(4,send_data_buffer_size);
  18.           }         
  19. }  
复制代码

论坛徽章:
1
2015年辞旧岁徽章
日期:2015-03-03 16:54:15
3 [报告]
发表于 2015-04-17 14:59 |只看该作者

  1. #include "tcp.h"

  2. //int n=0; //  移动到tcp.h

  3. struct epoll_event ev;// epoll事件结构体
  4. struct epoll_event events[MAX_EVENTS_TCP];// 事件监听队列
  5. int server_sock_fd_tcp;// 服务器端套接字   
  6. int client_sock_fd_tcp;// 客户端套接字      
  7. int nfds_tcp;// epoll监听事件发生的个数
  8. int len_recv_data_tcp;
  9. struct sockaddr_in host_addr_tcp;   // 服务器网络地址结构体   
  10. struct sockaddr_in remote_addr_tcp; // 客户端网络地址结构体   
  11. int sin_size;   
  12. unsigned char send_data_buffer_size_tcp[BUFFER_SIZE_TCP];  // 数据传送的缓冲区     
  13. int m=0;

  14. //设置句柄为非阻塞方式
  15. int setnonblocking(int sockfd)  
  16. {  
  17. if (fcntl(sockfd, F_SETFL, fcntl(sockfd, F_GETFD, 0)|O_NONBLOCK) == -1)  
  18. {  
  19.     return -1;  
  20. }  
  21.     return 0;  
  22. }


  23. int tcp_send_data_to_pc(int len,char* buffer)
  24. {
  25.                 printf("in while n == %d \n",n);
  26.                 send(events[n].data.fd,buffer,8,0);               
  27.                 ev.events = EPOLLIN;
  28.                 ev.data.fd = events[n].data.fd;
  29.     epoll_ctl(epoll_fd_tcp, EPOLL_CTL_MOD, ev.data.fd, &ev);
  30.    
  31. }

  32. void tcp_initialize()
  33. {
  34.     struct rlimit rt;
  35.    
  36.     /* 设置每个进程允许打开的最大文件数 */  
  37.     rt.rlim_max = rt.rlim_cur = 1024;  
  38.     if (setrlimit(RLIMIT_NOFILE, &rt) == -1)   
  39.                 {  
  40.         perror("setrlimit");  
  41.         exit(1);  
  42.     }  
  43.     else   
  44.     {  
  45.         printf("setrlimit ok! \n");  
  46.     }  
  47.    
  48.     // 创建服务器端套接字--IPv4协议,面向连接通信,TCP协议
  49.     if((server_sock_fd_tcp=socket(PF_INET,SOCK_STREAM,0))<0)   
  50.     {     
  51.         perror("socket");   
  52.         //return 1;   
  53.     }
  54.     else
  55.     {
  56.             printf("Tcp server socket ok...\n");
  57.     }
  58.            
  59.             // 设置 socket属性,端口可以重用   
  60.   
  61.           int opt=SO_REUSEADDR;
  62.           setsockopt(server_sock_fd_tcp,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(opt));
  63.           setnonblocking(server_sock_fd_tcp);
  64.            
  65.     memset(&host_addr_tcp,0,sizeof(host_addr_tcp)); // 数据初始化--清零      
  66.     host_addr_tcp.sin_family=PF_INET; // 设置为IP通信   
  67.     host_addr_tcp.sin_addr.s_addr=inet_addr(HOST_IP_ADDRESS_TCP);// 服务器IP地址--允许连接到所有本地地址上   
  68.     host_addr_tcp.sin_port=htons(HOST_PORT_TCP); // 服务器端口号  
  69.    
  70.     // 将套接字绑定到服务器的网络地址上
  71.     if (bind(server_sock_fd_tcp,(struct sockaddr *)&host_addr_tcp,sizeof(struct sockaddr))<0)   
  72.     {   
  73.         perror("bind");   
  74.         //return 1;   
  75.     }
  76.     else
  77.     {
  78.             printf("Tcp server bind ok...\n");
  79.             printf("IP  : %s   \n", inet_ntoa(host_addr_tcp.sin_addr));
  80.             printf("port: %d \n",ntohs(host_addr_tcp.sin_port));
  81.     }
  82.     // 监听连接请求--监听队列长度为5
  83.     listen(server_sock_fd_tcp,64);   
  84.     sin_size=sizeof(struct sockaddr_in);
  85.        
  86. }

  87. // 创建一个epoll句柄
  88. int create_epoll_tcp(unsigned int event_num)
  89.   {       
  90.           int epoll_fd;
  91.                 epoll_fd=epoll_create(event_num);
  92.                 if(epoll_fd==-1)
  93.                 {
  94.                         perror("epoll_create failed");                       
  95.                 }
  96.                 ev.events=EPOLLIN | EPOLLET;
  97.                 ev.data.fd=server_sock_fd_tcp;
  98.                 // 向epoll注册server_sockfd监听事件
  99.                 if(epoll_ctl(epoll_fd,EPOLL_CTL_ADD,server_sock_fd_tcp,&ev)==-1)
  100.                 {
  101.                         perror("epll_ctl:server_sock_fd_tcp register failed");                       
  102.                 }
  103.                 else
  104.           {
  105.             printf("socket adding in  epoll success! \n");
  106.           }
  107.                 return epoll_fd;
  108. }

  109. void do_process_tcp_nowhile()
  110. {                         
  111.                         // 等待事件发生
  112.                         nfds_tcp=epoll_wait(epoll_fd_tcp,events,1024,-1);
  113.                         if(nfds_tcp==-1)
  114.                         {
  115.                                 perror("start epoll_wait failed");
  116.                                 //exit(EXIT_FAILURE);
  117.                         }
  118.                         else
  119.                         {
  120.                                         printf(" epoll nfds_tcp = %d   \n",nfds_tcp);
  121.                         }
  122.                        
  123.                         for(n=0;n<nfds_tcp;++n)
  124.                         {
  125.                                 printf(" for loop epoll nfds_tcp = %d   \n",nfds_tcp);
  126.                                 // 客户端有新的连接请求
  127.                                 if(events[n].data.fd == server_sock_fd_tcp)
  128.                                 {
  129.                                         // 等待客户端连接请求到达
  130.                       if((client_sock_fd_tcp=accept(server_sock_fd_tcp,(struct sockaddr *)&remote_addr_tcp,&sin_size))<0)
  131.                                         {   
  132.                                                 perror("accept client_sock_fd_tcp failed");   
  133.                                                 exit(EXIT_FAILURE);
  134.                                         }
  135.                                         // 向epoll注册client_sockfd监听事件
  136.                                         setnonblocking(client_sock_fd_tcp);
  137.                                         ev.events=EPOLLIN | EPOLLET;
  138.                                         ev.data.fd=client_sock_fd_tcp;
  139.                                         if(epoll_ctl(epoll_fd_tcp,EPOLL_CTL_ADD,client_sock_fd_tcp,&ev)==-1)
  140.                                         {
  141.                                                 perror("epoll_ctl:client_sock_fd_tcp register failed");
  142.                                                 //exit(EXIT_FAILURE);
  143.                                         }
  144.                                         printf("accept client %s\n",inet_ntoa(remote_addr_tcp.sin_addr));
  145.                                                
  146.                                 }
  147.                                 else if(events[n].events & EPOLLIN)
  148.                                 {
  149.                                         // 客户端有数据发送过来
  150.                                         sprintf(send_data_buffer_size_tcp,"");
  151.                                         //sin_size=sizeof(remote_addr_tcp);
  152.                                
  153.                                         len_recv_data_tcp=recv(events[n].data.fd,send_data_buffer_size_tcp,BUFFER_SIZE_TCP,0);
  154.                                         if(len_recv_data_tcp<=0)
  155.                                         {
  156.                                                 printf("close id is : %d \n",events[n].data.fd);                                       
  157.                                                 if(epoll_ctl(epoll_fd_tcp,EPOLL_CTL_DEL,events[n].data.fd,&ev)==0)
  158.                                                 {
  159.                                                         printf("delete ok \n");
  160.                                                         close(events[n].data.fd);
  161.                                                 }
  162.                                                 else
  163.                                                 {
  164.                                                         printf("delete error \n");
  165.                                                 }
  166.                                         }
  167.                                         else
  168.                                         {
  169.                                                 printf("current recv fd is : %d \n",events[n].data.fd);
  170.                                                 printf("recv data: %d\n ",len_recv_data_tcp);
  171.                                                 for(m=0;m<4;m++)
  172.                                              printf("  %02X",send_data_buffer_size_tcp[m]);
  173.                                      printf("\n");       
  174.                                      printf("\n");       
  175.                                                 ev.data.fd = events[n].data.fd;
  176.             ev.events = EPOLLOUT|EPOLLET;
  177.             epoll_ctl(epoll_fd_tcp, EPOLL_CTL_MOD, events[n].data.fd, &ev);                                                       
  178.                                         }
  179.                                 }
  180.                                 else if(events[n].events & EPOLLOUT)//发送
  181.                                 {
  182.                                         tcp_send_data_to_pc(4,send_data_buffer_size_tcp);
  183.                                         tcp_send_data_to_pc(4,send_data_buffer_size_tcp);                                       
  184.                                         printf(" n == %d \n",n);
  185.                                 }
  186.                         }                       
  187.                
  188.                 if(server_sock_fd_tcp>0)
  189.                 {
  190.                         printf("socket close \n");
  191.                         shutdown(server_sock_fd_tcp,SHUT_RDWR);
  192.                         close(server_sock_fd_tcp);
  193.                 }
  194. }
复制代码

论坛徽章:
1
2015年辞旧岁徽章
日期:2015-03-03 16:54:15
4 [报告]
发表于 2015-04-17 15:00 |只看该作者

  1. #define BUFFER_SIZE_TCP 40
  2. #define MAX_EVENTS_TCP 10
  3. #define HOST_IP_ADDRESS_TCP "192.168.1.102"
  4. #define HOST_PORT_TCP 4530

  5. int n;
  6. int epoll_fd_tcp;
  7. int tcp_send_data_to_pc(int len,char* buffer);
  8. void tcp_initialize();
  9. int create_epoll_tcp(unsigned int event_num);
  10. void do_process_tcp();
  11. void do_process_tcp_nowhile();
  12. void set_tcp_event_out();
复制代码

论坛徽章:
15
射手座
日期:2014-11-29 19:22:4915-16赛季CBA联赛之青岛
日期:2017-11-17 13:20:09黑曼巴
日期:2017-07-13 19:13:4715-16赛季CBA联赛之四川
日期:2017-02-07 21:08:572015年亚冠纪念徽章
日期:2015-11-06 12:31:58每日论坛发贴之星
日期:2015-08-04 06:20:00程序设计版块每日发帖之星
日期:2015-08-04 06:20:00程序设计版块每日发帖之星
日期:2015-07-12 22:20:002015亚冠之浦和红钻
日期:2015-07-08 10:10:132015亚冠之大阪钢巴
日期:2015-06-29 11:21:122015亚冠之广州恒大
日期:2015-05-22 21:55:412015年亚洲杯之伊朗
日期:2015-04-10 16:28:25
5 [报告]
发表于 2015-04-17 20:55 |只看该作者
本帖最后由 yulihua49 于 2015-04-17 20:56 编辑
sasinop 发表于 2015-04-17 15:00

http://bbs.chinaunix.net/thread-4174032-1-2.html
看 3  楼那个,应用只需调用SendNet即可,epoll,AIO什么的都封装了。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP