讲udp应用之前,我先简单说一下udp与tcp之间的区别。
udp | tcp |
容易丢包 | 保证数据正确性 |
程序结构简单 | 程序结构复杂 |
流模式 | 数据模式 |
对系统资源要求少 | 对系统资源要求多 |
无连接 | 连接 |
数据是无序的 | 数据有序 |
接下来简单讲一下udp收发包的应用(点对点的应用):
一,发包:
1,首先创建一个网络端点:
IPEndPoint ipep = new IPEndPoint(IPAdress.Parse(ip), 9050);
此类有两个参数:第一个是接收端的IP,第二个是接收端的端口号。
2,接下来创建一个UdpClient对象:
UdpClient udpClient=new UdpClient();
3,准备发送:
发送时候有同步和异步两种方式,两种方式都有多种重载方法,下面每个讲其中一种,具体用哪种,看各自的需要。
a.异步发送:
方法:BeginSend(...);
参数:
BeginSend
(
byte[] datagram,//要发送的数据字节数组
int bytes,//要发送的数据的长度
AsyncCallback requestCallback,//发送完成后的回调函数
object state//用户自己定义发送完成成后的返回状态,在requestCallback有体现。
);
EndSend
(
IAsyncResult result//BeginSend返回的IAsyncResult s
)
使用:
public void SendData(string ip,int port,object data)
{
IPEndPoint ipep = new IPEndPoint(IPAdress.Parse(ip), port);
UdpClient udpClient=new UdpClient();
udpClient.BeginSend(data,data.Length,ipep,SendComplete,new AsyncCallbackArg(ip,udpClient));
}
///<summary>
///发送完成后的回调函数
///</summary>
///<param name="param"></param>
private void sendComplete(IAsyncResult param)
{
AsyncCallbackArg arg=param.AsyncState as AsyncCallbackArg;//param.AsyncState 对应的就是BeginSend的最后一个参数state
using(UdpClient client=(UdpClient)param.AsyncState)
{
try
{
client.EndSend(param);//这句话必须得写,BeginSend()和EndSend()是成对出现的
}
catch(Exception ex)
{
....
}
}
//自己定义的返回状态参数类型
private struct AsyncCallbackArg
{
private UdpClient udpClient;
private string ipAddress;
public AsyncCallbackArg(string ip,string client)
{
udpClient=client;
ipAddress=ip;
}
}
b.同步发送:
方法:Send(...);
参数:
Send
(
byte[] datagram,//要发送的数据字节数组
int bytes,//要发送的数据的长度
IPEndPoint endPoint//接收端的ip和端口对象
);
使用:
public void SendData(string ip,int port,object data)
{
IPEndPoint ipep = new IPEndPoint(IPAdress.Parse(ip), port);
UdpClient udpClient=new UdpClient();
udpClient.Send(data,data.Length,ipep);
}
二,收包
1,首先需要给本地接收端指定一个端口号port。发送端发送数据之前需要传入的是接收端的ip和端口号。
2,接下来创建一个UdpClient对象:
UdpClient udpClient=new UdpClient(port);
3,准备接收:
接收时候同样也有有同步和异步两种方式。
a.异步接收:
方法:BeginReceive(...);
参数:
BeginReceive
(
AsyncCallback requestCallback,//接收完后的回调函数
object state//用户自己定义接收完成成后的返回状态,在requestCallback有体现。
);
EndReceive
{
IAsyncResult asyncResult,//BeginReceive返回的IAsyncResult
ref IPEndPoint remoteEp//获取的发送方的相关信息
}
使用:
private int m_Port;
private bool m_IsReceive;
private UdpClient m_ReceiveUdpClient;
private Thread m_ReceiveThread;
public void StartReceiveData(int port)
{
m_IsReceive=true;
m_Port=port;
m_ReceiveThread=new Thread();
m_ReceiveThread.IsBackground=true;
m_ReceiveThreads.start();
}
private void Receive()
{
m_ReceiveUdpClient=new UdpClient(m_Port);
byte[] data;
while(m_IsReceive)
{
if(m_ReceiveUdpClient.Client==null)
{
break;
}
if(m_ReceiveUdpClient.Client.Poll(-1,SelectMode.Selectread))
{
break;
}
try{
m_ReceiveUdpClient.BeginReceive(new AsyncCallBack(ReceiveComplete),m_ReceiveUdpClient);
}catch(Exception ex){ .....}
}
}
private void ReceiveComplete(IAsyncResult param)
{
UDPClient client=param.AsyncState as UDPClient ;//对应的就是BeginSend的最后一个参数state
try
{
IPEndPoint ipep = new IPEndPoint(IPAdress.Any,m_Port);
byte[] datas=client.EndReceive(param,ref ipep);//接受到的数据
}
catch(Exception ex) { .... }
}
b.同步接收:
方法:Receive(...);
参数:
Receive
(
ref IPEndPoint endPoint////获取的发送方的相关信息s
);
使用:
private int m_Port;
public void StartReceiveData(int port)
{
m_Port=port;
m_ReceiveThread=new Thread();
m_ReceiveThread.IsBackground=true;
m_ReceiveThread.start();
}
private void Receive()
{
m_ReceiveUdpClient=new UdpClient(m_Port);
byte[] data;
while(m_IsReceive)
{
if( m_ReceiveUdpClient.Client==null)
{
break;
}
if( m_ReceiveUdpClient.Client.Poll(-1,SelectMode.Selectread))
{
break;
}
try{
IPEndPoint ip=new IPEndPoint();
data= m_ReceiveUdpClient.Receive(ref ip);
}catch(Exception ex){ .....}
}
}
停止接收:
private void StopReceive()
{
m_IsReceive=false;
if(m_ReceiveUdpClient!=null)
{
m_ReceiveUdpClient.Close();
}
if(m_ReceiveThread!=null &&m_ReceiveThread.ThreadState==ThreadState.Running)
{
m_ReceiveThread.Abort();
}
}