资源链接:http://download.csdn.net/download/yuanchunsi/10159049


P2P穿透成功后,获得对端IP和端口通过ENet进行连接传输数据,解决了UDP丢包视频卡顿的问题!


服务端:

/** ===========================================================================**       Filename:  enetc.c*    Description:  *        Version:  1.0*        Created:  2017年12月11日 14时10分03秒*       Revision:  none*       Compiler:  gcc*         Author:   (ycs), *        Company:  ** ===========================================================================*/#include<string.h>
#include<pthread.h>
#include<stdio.h>
#include<stdlib.h>
#include"enet/enet.h"
//全局变量
pthread_t pthread_S;
pthread_t pthread_R;
ENetPeer *peer = NULL;
ENetHost *host = NULL;
ENetEvent event; //模拟媒体数据结构
typedef struct code_{char data[128];int size ;
}tmp_t;//发送数据线程,模拟项目框架
void *run_s(void*data){pthread_detach(pthread_self()); static int count = 0; while(1) {sleep(1);if(NULL != peer) {ENetPacket *packet = enet_packet_create(NULL,78,ENET_PACKET_FLAG_RELIABLE);//ENET_PACKET_FLAG_RELIABLE:这个flag表示支持丢包重发char tmp[78];snprintf(tmp,78,"%s count: %d","I am server",count++);//发送带有seq的数据模拟RTP的序列号,确保ENet发送无异常//strcpy((char*)packet->data,tmp);memcpy((char*)packet->data,tmp,78);//此处很重要,媒体数据不能用strcpy!!!enet_peer_send(peer,2,packet);enet_host_flush(host);}}}
//接收数据线程,模拟项目框架
void *run_R(void*data){pthread_detach(pthread_self()); static int count = 0; while (enet_host_service (host, &event, 5000)>=0)  {printf("event type == %d\n",event.type);if(event.type == ENET_EVENT_TYPE_CONNECT){peer = event.peer;char ip[256];ENetAddress remote = event.peer->address;enet_address_get_host_ip(&remote,ip,256);printf("ip %s port %d\n",ip,remote.port);} else if(event.type == ENET_EVENT_TYPE_RECEIVE){printf("datalenth %d  %s channel %d\n",event.packet->dataLength,event.packet->data,event.channelID);//接收媒体数据tmp_t tmp;tmp.size = event.packet->dataLength;memcpy(tmp.data,event.packet->data,tmp.size);printf("data: %s size: %d\n",tmp.data,tmp.size);enet_packet_destroy(event.packet);} else if(event.type == ENET_EVENT_TYPE_DISCONNECT){printf("peer is disconnect \n"); }}
}int main(){int ret = -1;if(enet_initialize())  {printf("init failed\n");  return -1;  }ENetAddress haddr;  haddr.host = ENET_HOST_ANY;haddr.port=1234;//创建本地Host,绑定地址和端口 host = enet_host_create(&haddr,  15,   //允许15个客户端连接 3,    //有3个channel0,  0);  if(host == NULL)  {printf("create failed\n");return -1;  }//模拟项目框架,发送和接收为两个线程ret = pthread_create(&pthread_S,NULL,run_s,NULL);ret = pthread_create(&pthread_R,NULL,run_R,NULL);getchar();enet_deinitialize();  return 0;}

客户端:

/** ===========================================================================**       Filename:  enetc.c*    Description:  *        Version:  1.0*        Created:  2017年12月11日 14时10分03秒*       Revision:  none*       Compiler:  gcc*         Author:   (ycs), *        Company:  ** ===========================================================================*/#include<string.h>
#include<pthread.h>
#include<stdio.h>
#include<stdlib.h>
#include"enet/enet.h"//全局变量
pthread_t pthread_S;
pthread_t pthread_R;ENetPeer *peer = NULL;
ENetHost *host = NULL;
ENetEvent event;  //发送数据线程,模拟项目框架
void *run_s(void*data){pthread_detach(pthread_self());static int count = 0; while(1) {sleep(1);if(NULL != peer) {ENetPacket *packet = enet_packet_create(NULL,78,ENET_PACKET_FLAG_RELIABLE);//ENET_PACKET_FLAG_RELIABLE:这个flag表示支持丢包重发char tmp[78];snprintf(tmp,78,"%s count: %d","I am client",count++);//发送带有seq的数据模拟RTP的序列号,确保ENet发送无异常//strcpy((char*)packet->data,tmp);memcpy((char*)packet->data,tmp,78);//此处很重要,媒体数据不能用strcpy!!!enet_peer_send(peer,2,packet);enet_host_flush(host);}}}
//接收数据线程,模拟项目框架
void *run_R(void*data){pthread_detach(pthread_self()); static int count = 0; while (enet_host_service (host, &event, 5000)>=0)  {printf("event type == %d\n",event.type);if(event.type == ENET_EVENT_TYPE_CONNECT){peer = event.peer;char ip[256];ENetAddress remote = event.peer->address;enet_address_get_host_ip(&remote,ip,256);printf("ip %s port %d\n",ip,remote.port);} else if(event.type == ENET_EVENT_TYPE_RECEIVE){printf("datalenth %d  %s channel %d\n",event.packet->dataLength,event.packet->data,event.channelID);enet_packet_destroy(event.packet);} else if(event.type == ENET_EVENT_TYPE_DISCONNECT){printf("peer is disconnect \n"); }}
}int main(){int ret = 0;//初始化if(enet_initialize())  {printf("init failed\n");  return -1;  }//创建本地HOST对象,客户端不需要绑定地址  host = enet_host_create(NULL,  1,   //只允许连接一个服务器  0,0,  0);  if(host == NULL)  {printf("create failed\n");return -1;  }ENetAddress paddr;  enet_address_set_host(&paddr,"192.168.0.110");//设备端IP地址,此地址为StunServer提供(P2P穿透成功)  paddr.port=1234;//设备端ENet端口,测试端口  //连接设备端ENet,3为设备端3个Channelpeer = enet_host_connect(host,&paddr,3,0);  if(peer == NULL)  {  printf("peer connect failed\n");return -1;  } //模拟项目框架,发送和接收为两个线程ret = pthread_create(&pthread_S,NULL,run_s,NULL);ret = pthread_create(&pthread_R,NULL,run_R,NULL);getchar();enet_deinitialize();  return 0;}

总结:

1、enet_peer_send():实质把发送数据insert_list。由enet_host_service接口内部实现send操作

2、ENetPacket *packet=enet_packet_create(NULL,ret,ENET_PACKET_FLAG_RELIABLE);

选择合适的FLAGS创建packet

  1. ENET_PACKET_FLAG_RELIABLE packet must be received by the target peer and resend attempts should be made until the packet is delivered
  2. ENET_PACKET_FLAG_UNSEQUENCED packet will not be sequenced with other packets not supported for reliable packets
  3. ENET_PACKET_FLAG_NO_ALLOCATE packet will not allocate data, and user must supply it instead
  4. ENET_PACKET_FLAG_UNRELIABLE_FRAGMENT packet will be fragmented using unreliable (instead of reliable) sends if it exceeds the MTU
  5. ENET_PACKET_FLAG_SENT whether the packet has been sent from all queues it has been entered into

3、enet_host_service():很重要,实质接收发送数据都在这个函数做的;包括event事件、获取list,ACK重发。

enet_protocol_dispatch_incoming_commands (ENetHost * host, ENetEvent * event);//list

enet_protocol_receive_incoming_commands(host, event));//接收

enet_protocol_send_outgoing_commands (ENetHost * host, ENetEvent * event, int checkForTimeouts);//发送及丢包统计

enet_protocol_send_acknowledgements (ENetHost * host, ENetPeer * peer);这个是判断发送ack,如果ack不正确,会将continueSending置为1,从而让这个while一直循环发送该包。

P2P穿透(ENet丢包重传)相关推荐

  1. Android IOS WebRTC 音视频开发总结(八十七)-- WebRTC中丢包重传NACK实现分析

    Android IOS WebRTC 音视频开发总结(八十七)-- WebRTC中丢包重传NACK实现分析 本文主要介绍WebRTC中丢包重传NACK的实现,作者:weizhenwei ,文章最早发表 ...

  2. android蓝牙丢包重传,华为TE Desktop Mobile软终端引领市场

    [IT168厂商动态] 华为自从2013年推出TE30以后,随着视讯行业的迅猛发展与客户对视讯要求的不断提高,华为继续推出了TE40.TE50.TE60三款全新的高清视频会议终端,能全方位覆盖从中小型 ...

  3. TCPIP协议栈的心跳、丢包重传、连接超时机制实例详解

    目录 1.问题概述 2.TCPIP协议栈的心跳机制 2.1.TCP中的ACK机制 2.2.TCPIP协议栈的心跳机制说明 2.3.修改TCPIP协议栈的默认心跳参数 3.libwebsockets开源 ...

  4. Wireshark tcptrace图关于丢包重传细节图解

    上周六写了< 在Wireshark的tcptrace图中看清TCP拥塞控制算法的细节(CUBIC/BBR算法为例)>,收到一封邮件,说我文中的图示画错了.         确实,关于CUB ...

  5. UDP 分片 与 丢包,UDP 真的比 TCP 高效吗?

    关注.星标公众号,直达精彩内容 素材来源:https://blog.csdn.net/LearnLHC/article/details/115268028 整理:技术让梦想更伟大 | 李肖遥 一.UD ...

  6. UDP 分片 与 丢包,UDP 真的比 TCP 高效吗?UDP 的应用场景

    目录 一.UDP 报文格式 二.UDP 分片 1.UDP 有发送缓存区吗? 1>.先说结论: 2>.逐步分析: 2.UDP 分片 1>.UDP 包最佳传输大小 2>.分片问题 ...

  7. 网络编程之网络丢包故障如何定位?如何解决?

    引言 本期分享一个比较常见的网络问题--丢包.例如我们去ping一个网站,如果能ping通,且网站返回信息全面,则说明与网站服务器的通信是畅通的,如果ping不通,或者网站返回的信息不全等,则很可能是 ...

  8. 云网络丢包故障定位全景指南

    作者简介:冯荣,腾讯云网络高级工程师,腾讯云网络核心开发人员. 万字长文  建议收藏 引言 本期分享一个比较常见的⽹络问题--丢包.例如我们去ping⼀个⽹站,如果能ping通,且⽹站返回信息全⾯,则 ...

  9. linux 丢包排查思路简述(tcp+rdma)

    linux 丢包排查思路简述 概述 网络包接收流程 网络包发送流程 丢包排查的思路 tcp排查方法 rdma排查方法 网络工具汇总 参考链接 概述 我们首先以tcp网络为例,谈谈linux系统如何收发 ...

最新文章

  1. 探React Hooks
  2. Android init.rc文件格式解析
  3. Weblogic Admin Console
  4. 智能机器人服务广州春运
  5. 文件包含和文件上传结合
  6. StringBuilder字符串缓冲区
  7. imagettftext php7,mac php7 imagettftext
  8. pat 乙级 1016 部分A+B(C++)
  9. Opencv——写入或读取数据到XML或YAML文件
  10. 爬虫案列:京东商城长裤信息获取
  11. 如何尽量规避XSS(跨站点脚本)攻击
  12. 蓝桥杯 ALGO-110 算法训练 字符串的展开
  13. eNSP进行配置网络模拟网络联通
  14. matlab批量裁剪图像并保存,matlab批量裁剪tif图片
  15. windows下如何使用配置七牛qshell命令工具
  16. 学习光线追踪(16)---折射计算[1]
  17. Rest Stops 题解
  18. 《Wasserstein GAN》继续 GAN
  19. uni-app App端优化
  20. MFC开发——卡拉OK字幕制作

热门文章

  1. JavaEE入门级别最全教程2--初学者必看
  2. Content-Type为“multipart/form-data“是什么意思?
  3. qt 菜单/右键快捷菜单 选项不可操作/背景/分隔线颜色样式表
  4. matlab randperm函数
  5. 写2300字关于灌注桩施工质量管控的文章
  6. 前端页面的序号顺序排列index
  7. 游戏中的AI玩伴,会是“神队友”吗?
  8. C语言实现链表的逆序的几种方式
  9. 推荐一款好用的在线笔记工具evernote
  10. C. Yet Another Tournament