读书人

C# C/S UDP一对多异步通信解决思路

发布时间: 2013-09-29 11:07:08 作者: rapoo

C# C/S UDP一对多异步通信
服务器端:

public class StateObject
{
//服务器端
public Socket udpServer = null;
//接受数据缓冲区
public byte[] buffer = new byte[10*1024];
//远程终端
public EndPoint remoteEP;

public bool flag = false;
}


  private void ServerForm_Load(object sender, EventArgs e)
{
StartServer startServer = new StartServer();
thread = new Thread(new ThreadStart(startServer.ServerBind));
thread.Start();
}

#region 服务器绑定终端节点
        public void ServerBind()
{
//主机IP
IPEndPoint serverIp = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 8686);
Socket udpServer = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
udpServer.Bind(serverIp);
IPEndPoint clientIp = new IPEndPoint(IPAddress.Any, 0);
state = new StateObject();
state.udpServer = udpServer;
state.remoteEP = (EndPoint)clientIp;
AsynRecive();
}
#endregion

#region 异步接受消息
public void AsynRecive()
{
lock (state)
{
state.udpServer.BeginReceiveFrom(state.buffer, 0, state.buffer.Length, SocketFlags.None, ref state.remoteEP,
new AsyncCallback(ReciveCallback), null);
receiveDone.WaitOne();
}
}
#endregion

#region 异步接受消息回调函数
public void ReciveCallback(IAsyncResult asyncResult)
{
if (asyncResult.IsCompleted)
{
//获取发送端的终节点
IPEndPoint ipep = new IPEndPoint(IPAddress.Any, 0);
EndPoint remoteEP = (EndPoint)ipep;
state.udpServer.EndReceiveFrom(asyncResult, ref remoteEP);
data = new byte[10*1024];
state.buffer.CopyTo(data, 0);
state.buffer = new byte[10*1024];
int i = 0;
///取出命令
for (i = 0; i < leng; i++)
{
if (Convert.ToInt32(data[i]) == 0)


break;
}
byte[] cmdbyte = new byte[i];
for (int k = 0; k < i; k++)
{
cmdbyte[k] = data[k];
}
commandStr = Encoding.ASCII.GetString(cmdbyte);
if(!commandStr.Equals("connect"))
MessageBox.Show(commandStr, "kkk");
handleMsg(commandStr);

state.remoteEP = remoteEP;
receiveDone.Set();
AsynRecive();//继续接受消息
}
}
#endregion

#region 异步发送消息
public void AsynSend(byte[] buffer)
{
state.udpServer.BeginSendTo(buffer, 0, buffer.Length, SocketFlags.None, state.remoteEP,
new AsyncCallback(SendCallback), null);
sendDone.WaitOne();
}
#endregion

#region 异步发送消息回调函数
public void SendCallback(IAsyncResult asyncResult)
{
//消息发送完毕
if (asyncResult.IsCompleted)
{
state.udpServer.EndSendTo(asyncResult);
}
sendDone.Set();
}
#endregion
private void handleMsg(String msg)
{

}



客户端:
 public class StateObject
{
//客户端套接字
public Socket udpClient = null;
//接收信息缓冲区
public byte[] buffer = new byte[10*1024];
//服务器端终节点
public IPEndPoint serverIp;
//远程终端节点
public EndPoint remoteEP;

}

 private void 登陆_Load(object sender, EventArgs e)
{
contactWithServer = new ContactWithServer(this);
clientcontactserverThread = new Thread(new ThreadStart(contactWithServer.AsynRecive));
clientcontactserverThread.Start();
}


public ContactWithServer(登陆 loginForm)
{
this.loginForm = loginForm;
state = new StateObject();
state.udpClient = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
state.serverIp = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 8686);


state.remoteEP = (EndPoint)(new IPEndPoint(IPAddress.Any, 0));
//此处注意:
// 由于当前是客户端,所以没有绑定终节点
// 不可直接接收消息,必须先向其他终端发送信息告知本机终节点
string msg = "connect";
byte[] buffer = Encoding.ASCII.GetBytes(msg);
AsynSend(buffer);
}
#region 异步接收来自其他终端发送的消息
public void AsynRecive()
{
state.udpClient.BeginReceiveFrom(state.buffer, 0, state.buffer.Length, SocketFlags.None, ref state.remoteEP,
new AsyncCallback(ReciveCallback), null);
receiveDone.WaitOne();
}
#endregion

#region 异步接收来自其他终端发送的消息回调函数
public void ReciveCallback(IAsyncResult asyncResult)
{
//信息接收完成
if (asyncResult.IsCompleted)
{
state.udpClient.EndReceiveFrom(asyncResult, ref state.remoteEP);
data=new byte[10*1024];
state.buffer.CopyTo(data,0);
if (data.Length < 20) //只有命令
commandStr = Encoding.ASCII.GetString(data);
else
{
int i = 0;
///取出命令
for (i = 0; i < leng; i++)
{
if (Convert.ToInt32(data[i]) == 0)
break;
}
byte[] cmdbyte = new byte[i];
for (int k = 0; k < i; k++)
{
cmdbyte[k] = data[k];
}
commandStr = Encoding.ASCII.GetString(cmdbyte);
}
MessageBox.Show(commandStr, "来自服务器的命令!");
handleMsg(commandStr);
state.buffer=new byte[10*1024];


AsynRecive();
receiveDone.Set();
}
}
#endregion

#region 异步发送消息
public void AsynSend(byte[] buffer)
{
state.udpClient.BeginSendTo(buffer, 0, buffer.Length, SocketFlags.None, state.serverIp,
new AsyncCallback(SendCallback), null);
sendDone.WaitOne();
}
#endregion

#region 异步发送消息回调函数
public void SendCallback(IAsyncResult asyncResult)
{
//消息发送完成
if (asyncResult.IsCompleted)
{
state.udpClient.EndSendTo(asyncResult);
}
sendDone.Set();
}
#endregion


上面的代码可以正确实现服务器与客户端一对一的通信,但是我现在需要一对多的,该怎样修改呢?
[解决办法]
private delegate void WriteWrongLogHandle(string str);
private delegate void WriteLogHandle(byte[] byteData);
//本机IP地址
private IPEndPoint localEP;
//将要发送的IP地址
// private EndPoint RemotePoint;
//网络端口
Socket listener = null;//udp
private static bool isListener = true;//控制服务器监控服务

Dictionary<string, EndPoint> dic = null; //IP信息字典
private static readonly object padlock = new object();
private int MessageLength;//数据包大小

private int OperationCode;//操作内码
private Socket handle;
private BranchInfo info = null;
private string BranchNo;//机构内码
private int MsgThreadNum;//运行通讯线程数目
private int PortNum;//端口数目
private string ServerIp;//
private ManualResetEvent receiveDone = null;
private bool IsLog = false; //是否写日志


#region 服务启动
protected override void OnStart(string[] args)
{
try
{
// TODO: 在此处添加代码以启动服务。

//启动PosConm服务时开始写日志
// Utils.WriteLogFile("正在启动ConsumeSmg服务...");
String strFileName = AppDomain.CurrentDomain.BaseDirectory + "\\ConsumeMsg.xml";
XmlDocument doc = new XmlDocument();
doc.Load(strFileName);


// WriteExceptionLog(strFileName);
XmlNodeList listNode = doc.GetElementsByTagName("settings");
foreach (XmlNode node in listNode[0].ChildNodes)
{
switch (node.Name)
{
case "ServerIp":
ServerIp = node.InnerText;
break;
case "PortNum":
PortNum = Convert.ToInt32(node.InnerText);
break;
case "MsgThreadNum":
MsgThreadNum = Convert.ToInt32(node.InnerText);
break;
case "IsLog":
IsLog = Convert.ToBoolean(Convert.ToInt32(node.InnerText));
break;
default:
break;
}
}
if (IsLog)
{
WriteExceptionLog("正在启动ConsumeSmg服务...");
}
dic = new Dictionary<string, EndPoint>(); //IP信息字典
info = new BranchInfo();
receiveDone = new ManualResetEvent(false);
listener = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);//udp
localEP = new IPEndPoint(IPAddress.Any, PortNum);
listener.Bind(localEP);
isListener = true;
if (IsLog)
{
WriteExceptionLog(ServerIp + "[" + PortNum + "]");
}

try
{


//开多线程通讯
//for (int i = 0; i < MsgThreadNum; i++)
//{
Thread acceptWorkThread = new Thread(AcceptWorkThread);
acceptWorkThread.Start();
//}

Thread updateDicThread = new Thread(new ThreadStart(UpdateDictionaryThread));
updateDicThread.Start();


}
catch (Exception ex)
{
if (IsLog)
{
WriteExceptionLog("开始启动接收线程" + ex.Message);
}

}
}
catch (Exception ex)
{
if (IsLog)
{
WriteExceptionLog("启动服务失败:" + ex.Message);
}
Stop();
}
}
#endregion

public void AcceptWorkThread()
{
////本机IP从XML文件中读取

try
{


//异步接收数据

info = new BranchInfo();
info.Socket = listener;
listener.BeginReceiveFrom(info.Buffer, 0, info.Buffer.Length, SocketFlags.None, ref info.RePoint, new AsyncCallback(ReceiveCallBack), info);
receiveDone.WaitOne();
Thread.Sleep(100);
if (IsLog)
{
WriteExceptionLog("打印从客户端传输过来的字节数组");
}

//WriteByteDataLog(info.Buffer);

}
catch (Exception ex)
{
if (IsLog)


{
WriteExceptionLog("异步接收短消息" + ex.Message);
}
Stop();
}
}
服务端
[解决办法]
using System;
using System.Collections.Generic;
using System.Text;
using System.Net.Sockets;
using System.Net;

namespace tti365.ConsumeSmg365WS.Common
{
class BranchInfo
{
private byte[] _Buffer = new byte[4 * 1024];//接收数据缓存
private Socket _Socket;//客户端套接字
private int _MessageLength;//文件头大小

private int _OperationCode;//操作码

private byte[] _SendBuffer = new byte[4 * 1024];//发送数据的缓存
private int _ErrorTime;
private string _BranchNo;
private DateTime _Time;
public EndPoint RePoint =(EndPoint)new IPEndPoint(IPAddress.Any,0) ;

/// <summary>
/// UDP 套接字包
/// </summary>
public Socket Socket
{
set { _Socket = value; }
get { return _Socket; }
}

/// <summary>
/// 发送短IP
/// </summary>
//public EndPoint RePoint
//{
// set { _RePoint = value; }
// get { return _RePoint; }
//}

/// <summary>
/// 数据缓存包

/// </summary>
public byte[] Buffer
{
set { _Buffer = value; }
get { return _Buffer; }
}

/// <summary>
/// 数据包大小

/// </summary>
public int MessageLength
{
set { _MessageLength = value; }
get { return _MessageLength; }
}

/// <summary>
/// 操作码

/// </summary>
public int OperationCode
{
set { _OperationCode = value; }
get { return _OperationCode; }
}

/// <summary>
/// 发送数据包
/// </summary>
public byte[] SendBuffer
{
set { _SendBuffer = value; }
get { return _SendBuffer; }


}

/// <summary>
/// 错误次数
/// </summary>
public int ErrorTime
{
set { _ErrorTime = value; }
get { return _ErrorTime; }
}

/// <summary>
/// 接收机构类码
/// </summary>
public string BranchNo
{
set { _BranchNo = value; }
get { return _BranchNo; }
}


/// <summary>
/// 时间
/// </summary>
public DateTime Time
{
set { _Time = value; }
get { return _Time; }
}
}
}

[解决办法]
C# C/S UDP一对多异步通信解决思路

读书人网 >C#

热点推荐