C# C/S UDP一对多异步通信

w_angfei 2013-09-26 08:04:58
服务器端:
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

上面的代码可以正确实现服务器与客户端一对一的通信,但是我现在需要一对多的,该怎样修改呢?
...全文
3186 14 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
14 条回复
切换为时间正序
请发表友善的回复…
发表回复
a1295962107 2014-12-27
  • 打赏
  • 举报
回复
你解决了吗1对多
a1295962107 2014-12-27
  • 打赏
  • 举报
回复
哪句代码位置写错了
WayToAccept 2014-05-04
  • 打赏
  • 举报
回复
楼主最后怎么实现一对多的,可否告知,最近做一个即时通信也遇到问题了
华为黑名单 2013-09-27
  • 打赏
  • 举报
回复
引用 7 楼 u011443241 的回复:
希望以后谁写这块少走点弯路。。。
localEP = new IPEndPoint(IPAddress.Any, PortNum); listener.Bind(localEP); 搞了2次!我的代码可以直接拿着用!
linuxca 2013-09-27
  • 打赏
  • 举报
回复
w_angfei 2013-09-27
  • 打赏
  • 举报
回复
希望以后谁写这块少走点弯路。。。
华为黑名单 2013-09-27
  • 打赏
  • 举报
回复
逻辑确实没什么问题!
华为黑名单 2013-09-27
  • 打赏
  • 举报
回复
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; } } } }
w_angfei 2013-09-27
  • 打赏
  • 举报
回复
找见问题了,一句代码的位置写错了,太不仔细了,这个逻辑是没问题的
华为黑名单 2013-09-27
  • 打赏
  • 举报
回复
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(); } } 服务端
w_angfei 2013-09-27
  • 打赏
  • 举报
回复
这是怎么了,都没人来看看
w_angfei 2013-09-27
  • 打赏
  • 举报
回复
引用 9 楼 luodayoudianzi 的回复:
[quote=引用 7 楼 u011443241 的回复:] 希望以后谁写这块少走点弯路。。。
localEP = new IPEndPoint(IPAddress.Any, PortNum); listener.Bind(localEP); 搞了2次!我的代码可以直接拿着用![/quote]搞了两次是什么意思?
w_angfei 2013-09-26
  • 打赏
  • 举报
回复
自己顶下,大家帮忙看看吧

111,097

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • AIGC Browser
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧