青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

隨筆-162  評論-223  文章-30  trackbacks-0
場景說明
   選擇ENet代替TCP用于弱網環境(通常丟包率高)的數據傳輸,提高可靠性及傳輸效率。為了說明怎樣正確有效地應用ENet,本文按照TCP C/S同步通信的流程作了對應的接口封裝實現,取庫名為rudp。

接口對照
   左邊為rudp庫的API,右邊為標準的Berkeley套接字API。rudp庫所有API前綴為rudp,rudp_listen和rudp_accept僅用于服務端,rudp_connect和rudp_disconnect僅用于客戶端;其它接口共用于兩端,其中rudp_send調用rudp_sendmsg實現,rudp_recv調用rudp_recvmsg實現。
                   

具體實現

   所有接口遵循Berkeley套接字接口的語義,為簡單起見,錯誤描述輸出到標準錯誤流。
   ◆ 監聽,成功返回0,失敗返回-1
 1 int rudp_listen(const char *ip, int port, ENetHost **host)
 2 {    
 3     ENetAddress address;    
 4 
 5     if(!strcmp(ip, "*"))
 6            ip = "0.0.0.0";
 7 
 8     if(enet_address_set_host_ip(&address, ip)){
 9           fprintf(stderr, "enet_address_set_host_ip %s fail", ip);
10         return -1;
11     }
12     
13     address.port = port;
14     
15     assert(host);
16     *host = enet_host_create(&address, 1, 1, 0, 0);
17     if(NULL==*host){
18           fprintf(stderr, "enet_host_create %s:%d fail", address.host, address.port);
19         return -1;
20     }
21 
22     int size = 1024*1024*1024;
23     if(enet_socket_set_option((*host)->socket, ENET_SOCKOPT_RCVBUF, size)){
24            fprintf(stderr, "enet set server socket rcvbuf %d bytes fail", size);
25     }
26 
27     return 0;
28 }

   ◆ 接受連接,成功返回0,失敗返回-1
 1 int rudp_accept(ENetHost *host, unsigned int timeout, ENetPeer **peer)
 2 {
 3     int ret;
 4     ENetEvent event;
 5 
 6     ret = enet_host_service(host, &event, timeout);
 7     if(ret > 0){        
 8         if(event.type != ENET_EVENT_TYPE_CONNECT){
 9             if(event.type == ENET_EVENT_TYPE_RECEIVE)
10                 enet_packet_destroy(event.packet);
11             fprintf(stderr, "enet_host_service event type %d is not connect", event.type);
12             return -1;
13         }
14         
15         assert(peer);
16         *peer = event.peer;
17         
18     }else if(0==ret){
19         fprintf(stderr, "enet_host_service timeout %d", timeout);
20         return -1;
21         
22     }else{
23         fprintf(stderr, "enet_host_service fail");
24         return -1;
25     }    
26 
27     return 0;
28 }
   
   ◆ 建立連接,成功返回0,失敗返回-1,conn_timeout是連接超時,rw_timeout是收發超時,單位為毫秒
 1 int rudp_connect(const char *srv_ip, int srv_port, unsigned int conn_timeout, unsigned int rw_timeout, ENetHost **host, ENetPeer **peer)
 2 {    
 3     assert(host);
 4     *host = enet_host_create(NULL, 1, 1, 0, 0);
 5     if(NULL==*host){
 6         fprintf(stderr, "enet_host_create fail");
 7         goto fail;
 8     }
 9     if(enet_socket_set_option((*host)->socket, ENET_SOCKOPT_RCVBUF, 1024*1024*1024)){
10            fprintf(stderr, "enet set server socket rcvbuf 1M bytes fail");
11     }
12     
13     ENetAddress srv_addr;
14     if(enet_address_set_host_ip(&srv_addr, srv_ip)){
15         fprintf(stderr, "enet_address_set_host_ip %s fail", srv_ip);
16         goto fail;
17     }
18     srv_addr.port = srv_port;
19     
20     assert(peer);
21     *peer = enet_host_connect(*host, &srv_addr, 1, 0); 
22     if(*peer==NULL){
23             fprintf(stderr, "enet_host_connect %s:%d fail", srv_ip, srv_port);
24         goto fail;
25     }
26 
27     enet_peer_timeout(*peer, 0, rw_timeout, rw_timeout);
28     
29     int cnt = 0;
30     ENetEvent event;
31 
32     while(1){
33         ret = enet_host_service(*host, &event, 1);
34         if(ret == 0){    
35             if(++cnt >= conn_timeout){ 
36                    fprintf(stderr, "enet_host_service timeout %d", conn_timeout);
37                 goto fail;
38             }
39         
40         }else if(ret > 0){
41             if(event.type != ENET_EVENT_TYPE_CONNECT){     
42                     fprintf(stderr, "enet_host_service event type %d is not connect", event.type);
43                     goto fail;
44             }
45             break//connect successfully
46 
47         }else{
48                 fprintf(stderr, "enet_host_service fail");        
49             goto fail;
50         }
51     }
52 
53 #ifdef _DEBUG
54     char local_ip[16], foreign_ip[16];
55     ENetAddress local_addr;
56 
57     enet_socket_get_address((*host)->socket, &local_addr);
58     enet_address_get_host_ip(&local_addr, local_ip, sizeof(local_ip));
59     enet_address_get_host_ip(&(*peer)->address, foreign_ip, sizeof(foreign_ip));
60     
61     printf("%s:%d connected to %s:%d", local_ip, loca_addr.port, foreign_ip, (*peer)->address.port);
62 #endif
63 
64     return 0;
65     
66 fail:
67     if(*host) enet_host_destroy(*host); 
68     return -1;
69 }
   
    ◆ 斷開連接,若成功則返回0,超時返回1,出錯返回-1。先進行優雅關閉,如失敗再強制關閉
 1 int rudp_disconnect(ENetHost *host, ENetPeer *peer)
 2 {
 3     int ret;
 4 
 5 #ifdef _DEBUG
 6     char local_ip[16], foreign_ip[16];
 7     ENetAddress local_addr;
 8 
 9     enet_socket_get_address(host->socket, &local_addr);
10     enet_address_get_host_ip(&local_addr, local_ip, sizeof(local_ip));
11     enet_address_get_host_ip(&peer->address, foreign_ip, sizeof(foreign_ip));
12     
13     printf("%s:%d is disconnected from %s:%d", local_ip, local_addr.port, foreign_ip, peer->address.port);
14 #endif
15 
16     ENetEvent event;
17     enet_peer_disconnect(peer, 0);
18         
19     while((ret = enet_host_service(host, &event, peer->roundTripTime)) > 0){
20         switch (event.type){
21         case ENET_EVENT_TYPE_RECEIVE:
22             enet_packet_destroy (event.packet);
23             break;
24     
25         case ENET_EVENT_TYPE_DISCONNECT:
26             ret = 0;
27             goto disconn_ok;
28         }
29     }
30 
31     ret = 0==ret ? 1 : -1;
32 
33     fprintf(stderr, "enet_host_service with timeout %d %s", peer->roundTripTime, 1==ret?"timeout":"failure");
34     
35     enet_peer_reset(conn->peer);
36 
37 disconn_ok:    
38     enet_host_destroy(host);
39     return ret;
40 }

    ◆ 發送數據,若成功則返回已發送數據的長度,否則返回-1
 1 int rudp_sendmsg(ENetHost *host, ENetPeer *peer, ENetPacket *packet)
 2 {
 3     int ret;
 4     
 5     if(enet_peer_send(peer, 0, packet)){
 6         fprintf(stderr, "enet send packet %lu bytes to peer fail", packet->dataLength);
 7         return -1;
 8     }
 9 
10     ret = enet_host_service(host, NULL, peer->roundTripTime);
11     if(ret >= 0){
12         if(peer->state == ENET_PEER_STATE_ZOMBIE){
13             fprintf(stderr, "enet peer state is zombie");
14             return -1;
15         }
16         return packet->dataLength;
17         
18     }else{
19         fprintf(stderr, "enet host service %u millsecond failure", peer->roundTripTime);
20         return -1;
21     }
22 }
23 
24 int rudp_send(ENetHost *host, ENetPeer *peer, const void *buf, size_t len)
25 {
26     int ret;
27 
28     ENetPacket *packet = enet_packet_create(buf, len, ENET_PACKET_FLAG_RELIABLE);
29     if(NULL==packet){        
30         fprintf(stderr, "enet create packet %lu bytes fail", sizeof(int)+len);
31         return -1;
32     }
33 
34     return rudp_sendmsg(host, peer, packet);
35 }
   發送數據時需根據對端狀態判斷是否斷線,并且packet標志設為可靠

   ◆ 接收數據,若成功則返回已接收數據的長度,否則返回-1
 1 int rudp_recvmsg(ENetHost *host, ENetPeer *peer, ENetPacket **packet, unsigned int timeout)
 2 {
 3     int ret;
 4     ENetEvent event;
 5 
 6     ret = enet_host_service(host, &event, timeout);
 7     if(ret > 0){
 8         if(event.peer != peer){
 9             fprintf(stderr, "enet receive peer is not matched");
10             goto fail;
11         }
12         if(event.type != ENET_EVENT_TYPE_RECEIVE){
13             fprintf(stderr, "enet receive event type %d is not ENET_EVENT_TYPE_RECEIVE", event.type);
14             goto fail;
15         }
16         
17         *packet = event.packet;
18         return (*packet)->dataLength;
19         
20 fail:
21         enet_packet_destroy(event.packet);
22         return -1;
23         
24     }else {
25         fprintf(stderr, "enet receive %u millsecond %s", timeout, ret?"failure":"timeout");
26         return -1;        
27     }
28 }
29 
30 int rudp_recv(ENetHost *host, ENetPeer *peer, void *buf, size_t maxlen, unsigned int timeout) 
31 {
32     ENetPacket *packet;
33 
34     if(-1==rudp_recvmsg(host, peer, &packet, timeout))
35         return -1;
36 
37     if(packet->dataLength > maxlen) {
38         fprintf(stderr, "enet packet data length %d is greater than maxlen %lu", packet->dataLength, maxlen);
39         return -1;
40     }
41 
42     memcpy(buf, packet->data, packet->dataLength);
43     enet_packet_destroy(packet);
44     
45     return packet->dataLength;
46 }
   
   ◆ 等待所有確認,若成功返回0,超時返回1,失敗返回-1
 1 int rudp_wait_allack(ENetHost *host, ENetPeer *peer, unsigned int timeout)
 2 {
 3     int ret, cnt = 0;
 4     
 5     while((ret = enet_host_service(host, NULL, 1)) >= 0){        
 6         if(enet_peer_is_empty_sent_reliable_commands(peer, 0, 
 7             ENET_PROTOCOL_COMMAND_SEND_RELIABLE|ENET_PROTOCOL_COMMAND_SEND_FRAGMENT))
 8             return 0;
 9 
10         if(peer->state == ENET_PEER_STATE_ZOMBIE){
11             fprintf(stderr, "enet peer state is zombie");
12             return -1;
13         }
14     
15         if(0==ret && ++cnt>=timeout){
16             return 1;
17         }
18     }
19     
20     fprintf(stderr, "enet host service fail");
21     return -1;
22 }
    等待已發送數據的所有確認時,需根據對端狀態判斷是否斷線

示例流程   
   左邊為客戶端,壓縮并傳輸文件;右邊為服務端,接收并解壓存儲文件。
   

   客戶端【讀文件塊并壓縮】這個環節,需要顯式創建可靠packet,并將壓縮后的塊拷貝到其中
posted on 2020-05-04 19:08 春秋十二月 閱讀(2475) 評論(0)  編輯 收藏 引用 所屬分類: Network
青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            欧美巨乳在线观看| 亚洲国产欧美久久| 亚洲一区二区在线免费观看| 久久精品国产99精品国产亚洲性色| 免费高清在线一区| 亚洲欧美日韩精品久久久| 欧美成人免费观看| 尤物视频一区二区| 久久亚裔精品欧美| 久久av资源网| 国内精品久久久| 久久精品动漫| 欧美亚洲色图校园春色| 国产精品网站一区| 亚洲欧美视频| 亚洲一区二区高清| 欧美亚州一区二区三区| 亚洲人成在线播放| 亚洲精品乱码久久久久久日本蜜臀| 欧美一区二区黄| 亚洲精品国产日韩| 午夜伦欧美伦电影理论片| 午夜视频一区二区| 欧美日韩精品一区二区在线播放| 亚洲第一精品在线| 久久久视频精品| 午夜影院日韩| 国产欧美日韩不卡| 国产亚洲亚洲| 亚洲伊人第一页| 亚洲人成7777| 亚洲欧洲一级| 欧美日韩精品欧美日韩精品一| 亚洲精品女人| 欧美韩日一区二区| 欧美成人性网| av成人免费在线观看| 亚洲欧洲三级电影| 欧美va亚洲va日韩∨a综合色| 亚洲第一页中文字幕| 在线免费观看日本欧美| 六月丁香综合| 久久综合导航| 日韩视频一区二区| 亚洲精品在线三区| 欧美三级不卡| 欧美亚洲综合另类| 99精品国产福利在线观看免费| 欧美一区二区三区免费在线看| 国产麻豆午夜三级精品| 久久精品99国产精品| 欧美专区亚洲专区| 久久精品99| 久久嫩草精品久久久精品| 欧美日韩一区二区三区在线观看免| 一本高清dvd不卡在线观看| 99精品欧美一区| 国产欧美一级| 欧美激情精品久久久久久免费印度| 亚洲欧美国产高清| 国外成人网址| 亚洲精品美女久久7777777| 国产精品xxxav免费视频| 久久成人精品无人区| 卡通动漫国产精品| 中文国产一区| 久久精品国产免费看久久精品 | 国产一区二区在线免费观看 | 国产精品入口日韩视频大尺度| 一区二区三区久久| 亚洲精品在线二区| 午夜精彩视频在线观看不卡 | 免费成人av| 亚洲一区中文| 六十路精品视频| 欧美一区二区视频97| 欧美日韩三级一区二区| 欧美一区二区视频在线观看2020| 久久国产欧美精品| 日韩一级大片| 午夜久久电影网| 91久久精品美女| 亚洲欧美在线免费| 亚洲品质自拍| 欧美一区二区视频在线观看2020| 亚洲美女淫视频| 新67194成人永久网站| 亚洲毛片视频| 久久精品国产免费看久久精品| 在线综合亚洲欧美在线视频| 久久精品亚洲乱码伦伦中文 | 国产精品激情| 亚洲国产精品女人久久久| 国产精品永久免费| 亚洲毛片一区| 日韩视频精品| 免费毛片一区二区三区久久久| 欧美中文日韩| 国产精品久久久一区麻豆最新章节 | 免费成人av资源网| 老司机成人在线视频| 欧美日韩中文在线观看| 欧美国产精品人人做人人爱| 国产一区久久久| 先锋影院在线亚洲| 欧美一区二区三区成人| 欧美日韩在线三区| 日韩一本二本av| 一本色道**综合亚洲精品蜜桃冫 | 久久久五月天| 久久久久国产一区二区三区四区 | 亚洲精品1234| 国产精品v日韩精品v欧美精品网站| 久久夜色精品| 精品成人一区二区| 久久亚洲捆绑美女| 久久亚洲春色中文字幕久久久| 国产日韩在线看片| 亚洲欧美乱综合| 久久精选视频| 欧美三区视频| 性欧美1819性猛交| 久久精品人人| 亚洲欧洲视频| 欧美日韩一区在线播放| 9国产精品视频| 午夜精品成人在线| 久久综合给合久久狠狠狠97色69| 免费观看成人| 夜夜嗨av一区二区三区网页| 久久全球大尺度高清视频| 午夜精品一区二区三区电影天堂 | 亚洲一区二区免费在线| 久久久亚洲精品一区二区三区| 激情文学一区| 欧美激情第4页| 在线亚洲一区| 久久久久网站| 亚洲精品一二区| 欧美视频网址| 久久本道综合色狠狠五月| 免费成人高清视频| 一区二区久久| 国产一区二区按摩在线观看| 一区二区高清视频| 亚洲精品乱码久久久久久蜜桃麻豆 | 国产麻豆日韩欧美久久| 久久久久国产精品午夜一区| 欧美国产日韩视频| 亚洲网站视频福利| 国产日韩精品久久| 免费黄网站欧美| 亚洲一二三区精品| 欧美成人一区二区三区片免费| 99re在线精品| 韩国三级电影一区二区| 欧美日韩视频在线一区二区观看视频 | 欧美福利在线| 亚洲欧美日韩精品久久亚洲区 | 欧美日韩在线观看一区二区三区| 亚洲欧美一区二区三区久久 | 亚洲无玛一区| 亚洲激情午夜| 国产日韩欧美在线一区| 欧美成人免费在线观看| 久久一区激情| 亚洲一级黄色| 亚洲电影在线观看| 免费看亚洲片| 久久成人综合视频| 亚洲午夜国产成人av电影男同| 噜噜爱69成人精品| 久久爱91午夜羞羞| 亚洲免费综合| 正在播放亚洲一区| 亚洲国产欧美一区二区三区久久| 国产精品拍天天在线| 久久精品人人做人人爽| 亚洲一区欧美激情| 99精品视频一区| 欧美一区二区三区免费观看| 久久久久国产精品午夜一区| 一本大道久久a久久精品综合| 欧美成年人视频网站| 亚洲精品国产精品国自产观看浪潮| 国产欧美日韩在线播放| 欧美性大战xxxxx久久久| 欧美暴力喷水在线| 亚洲欧美日韩在线播放| 99视频精品在线| 91久久精品www人人做人人爽| 老司机67194精品线观看| 亚洲字幕一区二区| 亚洲视频在线观看一区| 一区二区三区日韩精品视频| 亚洲日本中文字幕区| 久久精品国产99国产精品澳门 | 欧美亚洲一区三区| 亚洲欧美一级二级三级| 亚洲午夜一级|