講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();
}
}
