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

隨筆-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>
            亚洲综合欧美日韩| 亚洲欧美综合精品久久成人| 欧美激情第五页| 欧美国产综合视频| 欧美成人免费播放| 欧美日韩伦理在线免费| 欧美午夜片在线免费观看| 国产精品爱啪在线线免费观看| 欧美日韩亚洲精品内裤| 国产精品美女久久久免费 | 欧美日韩国产精品一区| 欧美女人交a| 国产精品啊v在线| 狠狠入ady亚洲精品| 亚洲精品中文字幕在线观看| 亚洲免费视频成人| 欧美成人久久| 亚洲最黄网站| 久久九九国产精品| 欧美丝袜一区二区三区| 好看的日韩视频| 一区二区三区视频免费在线观看 | 欧美色视频在线| 国产日产欧产精品推荐色 | 久久久久久久综合日本| 欧美精品粉嫩高潮一区二区| 国产精品亚洲第一区在线暖暖韩国| 韩曰欧美视频免费观看| 亚洲网在线观看| 欧美国产三区| 欧美在线免费看| 国产精品国产一区二区| 亚洲美女电影在线| 久久久久久亚洲精品不卡4k岛国| 亚洲人成毛片在线播放| 午夜精品久久久久久久男人的天堂 | 欧美激情亚洲另类| 午夜精品久久久久久久| 欧美性猛交xxxx乱大交退制版| 在线观看国产日韩| 久久精品中文| 亚洲一区二区在线播放| 欧美日韩精品一区二区在线播放| 国产一区二区三区日韩| 亚洲欧美成人网| 日韩视频免费观看高清在线视频 | 国产精品久久看| 亚洲精品女av网站| 欧美国产精品日韩| 久久女同精品一区二区| 国产综合久久久久久| 亚洲午夜国产一区99re久久| 国产精品国产a级| 亚洲欧洲一区二区在线观看| 老司机午夜精品视频| 欧美一区午夜视频在线观看| 国产精品一区视频| 午夜国产精品视频免费体验区| 日韩午夜激情| 欧美四级剧情无删版影片| 亚洲午夜精品17c| 一区二区黄色| 国产精品国产亚洲精品看不卡15| 一区二区欧美亚洲| 一本色道久久综合亚洲精品高清| 欧美日韩国产一区| 一区二区欧美日韩| 一区二区三区导航| 久久久久国产精品午夜一区| 久久久爽爽爽美女图片| 欧美mv日韩mv亚洲| 亚洲二区视频| 老司机免费视频一区二区| 欧美色视频一区| 一区二区久久| 亚洲精品在线观看免费| 欧美日韩国产综合久久| 亚洲永久字幕| 久久se精品一区精品二区| 一区免费观看视频| 亚洲欧洲综合| 免费亚洲视频| 久久一区二区三区四区| 亚洲美女色禁图| 亚洲国产一区二区三区a毛片| 一卡二卡3卡四卡高清精品视频| 亚洲欧美日韩在线播放| 亚洲欧美另类国产| 在线观看成人一级片| 亚洲精品看片| 国产精品一区二区欧美| 欧美第一黄网免费网站| 欧美精品激情| 久久精品成人| 欧美日本视频在线| 久久精品在线免费观看| 欧美另类一区二区三区| 欧美一区二区三区男人的天堂 | 亚洲精品视频啊美女在线直播| 日韩一二在线观看| 国产一区二三区| 99精品福利视频| 亚洲高清一二三区| 亚洲欧美日韩专区| 一区二区三区黄色| 免费久久99精品国产| 小黄鸭视频精品导航| 午夜精品www| 六十路精品视频| 欧美一区二区三区在| 欧美人与性动交cc0o| 欧美成人福利视频| 国产亚洲毛片在线| 宅男噜噜噜66一区二区| 亚洲精品视频在线看| 久久gogo国模啪啪人体图| 亚洲一区黄色| 欧美欧美在线| 亚洲狠狠婷婷| 亚洲国产精品va在线看黑人动漫 | 亚洲激情在线| 久久久一本精品99久久精品66| 亚洲永久字幕| 欧美日韩国内自拍| 亚洲精品午夜精品| 亚洲欧洲一区二区三区在线观看| 午夜精品久久久久久久久久久| 亚洲一区二区少妇| 欧美小视频在线观看| 亚洲乱码精品一二三四区日韩在线| 午夜激情一区| 国产一区二区久久精品| 亚洲主播在线播放| 亚洲欧美www| 国产精品久久久久久久app| 亚洲理论电影网| 亚洲私人影院| 国产精品大片wwwwww| 亚洲毛片av| 欧美激情二区三区| 亚洲精品一二| 欧美日韩一区二区三| 亚洲国产精品va在线看黑人| 亚洲精品视频一区二区三区| 极品少妇一区二区三区精品视频| 亚洲一区二三| 久久久久在线| …久久精品99久久香蕉国产| 久久天天躁狠狠躁夜夜爽蜜月| 免费欧美日韩| 日韩一级在线| 国产精品久久久久毛片大屁完整版| 亚洲一级免费视频| 久久免费偷拍视频| 亚洲国产一区二区三区a毛片| 欧美国产激情| 亚洲午夜黄色| 欧美~级网站不卡| 99国产精品99久久久久久粉嫩| 欧美色欧美亚洲另类二区| 99re热这里只有精品视频| 艳妇臀荡乳欲伦亚洲一区| 亚洲高清av在线| 久久国内精品自在自线400部| 久久综合色88| 99re6热只有精品免费观看| 国产精品久久久久久久久久免费看 | 日韩视频中文字幕| 亚洲宅男天堂在线观看无病毒| 国产精品推荐精品| 乱码第一页成人| 亚洲午夜黄色| 欧美国产精品日韩| 久久久久免费观看| 亚洲精品一区二区三区不| 欧美一区二区三区在线观看视频| 国内伊人久久久久久网站视频 | 欧美一区二区在线| 久久综合久久久久88| 亚洲国产精品久久| 艳女tv在线观看国产一区| 欧美午夜精品理论片a级按摩| 午夜视黄欧洲亚洲| 亚洲韩国青草视频| 久久gogo国模裸体人体| 亚洲精品久久久久久久久久久久久 | 狠狠色丁香婷婷综合久久片| 模特精品裸拍一区| 一本色道久久加勒比精品| 欧美一级理论性理论a| 亚洲国产毛片完整版| 国产欧美一区二区精品性| 欧美日韩1区2区| 99国产精品国产精品久久| 欧美二区在线播放| 久久精品一区二区三区四区| 亚洲乱码国产乱码精品精98午夜 | 亚洲一区二区三区在线看 | 亚洲精品小视频| 韩日成人av|