C#完整的通信代码(二)(点对点,点对多,同步,异步,UDP,TCP)

下列范例使用 UdpClient,在通讯端口 11000 监听广播到多点传送位址群组 224.168.100.2 的 UDP 资料包。它接收信息字串,并將信息写入主控台 (Console)。 C# code using System; using System.Net; using System.Net.Sockets; using System.Text; public class UDPMulticastListener { private static readonly IPAddress GroupAddress = IPAddress.Parse("224.168.100.2"); private const int GroupPort = 11000; private static void StartListener() { bool done = false; UdpClient listener = new UdpClient(); IPEndPoint groupEP = new IPEndPoint(GroupAddress,GroupPort); try { listener.JoinMulticastGroup(GroupAddress); listener.Connect(groupEP); while (!done) { Console.WriteLine("Waiting for broadcast"); byte[] bytes = listener.Receive( ref groupEP); Console.WriteLine("Received broadcast from {0} :/n {1}/n", groupEP.ToString(), Encoding.ASCII.GetString(bytes,0,bytes.Length)); } listener.Close(); } catch (Exception e) { Console.WriteLine(e.ToString()); } } public static int Main(String[] args) { StartListener(); return 0; } } using System; using System.Net; using System.Net.Sockets; using System.Text; public class UDPMulticastSender { private static IPAddress GroupAddress = IPAddress.Parse("224.168.100.2"); private static int GroupPort = 11000; private static void Send( String message) { UdpClient sender = new UdpClient(); IPEndPoint groupEP = new IPEndPoint(GroupAddress,GroupPort); try { Console.WriteLine("Sending datagram : {0}", message); byte[] bytes = Encoding.ASCII.GetBytes(message); sender.Send(bytes, bytes.Length, groupEP); sender.Close(); } catch (Exception e) { Console.WriteLine(e.ToString()); } } public static int Main(String[] args) { Send(args[0]); return 0; } } C# code try { UdpClient udp=new UdpClient(new IPEndPoint(ipAddress,startPort+i)); udp.Close(); unUsedPort=startPort+i; break; } catch { } using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Text; using System.Windows.Forms; using System.Collections; using System.Collections.Specialized; using System.Threading; using System.Net.Sockets; using System.Net; using System.Runtime.Serialization; using System.Runtime.Serialization.Formatters.Binary; using System.IO; namespace 聊天工具服务器 { public partial class FormMain : Form { public FormMain() { InitializeComponent(); } #region 字段定义 /// <summary> /// 服务器程序使用的端口,默认为8888 /// </summary> private int _port = 8888; /// <summary> /// 接收数据缓冲区大小2K /// </summary> private const int _maxPacket =2 * 1024; /// <summary> /// 服务器端的监听器 /// </summary> private TcpListener _tcpl = null; Thread _receiveThread; /// <summary> /// 保存所有客户端会话的哈希表 /// </summary> private Hashtable _transmit_tb = new Hashtable(); /// <summary> /// 当前文件路径 /// </summary> string MyPath = null; /// <summary> /// 用户基本信息表,包括UserName,UserPwd,UserNich,UserImg,ZX,UserIp /// </summary> DataTable TabUser = new DataTable(); /// <summary> /// 用户消息表,保存用户不在线时的消息 /// </summary> DataTable TabUserMessage = new DataTable(); #endregion /// <summary> /// 序列化在线列表,向客户端返回序列化后的字节数组 /// </summary> /// <returns>序列化后的字节数组 </returns> private byte[] SerializeOnlineList() { StringCollection onlineList = new StringCollection(); foreach (object o in _transmit_tb.Keys) { onlineList.Add(o as string); } IFormatter format = new BinaryFormatter(); MemoryStream stream = new MemoryStream(); format.Serialize(stream, onlineList); byte[] ret = stream.ToArray(); stream.Close(); return ret; } /// <summary> /// 序列化好友列表,向客户端返回序列化后的datatable /// </summary> /// <returns>序列化后的字节数组 </returns> private bool SerializeFriendList(object obj, Socket clientSkt) { DataTable TabmyFriend = new DataTable(); TabmyFriend.TableName = obj as string; try { TabmyFriend.ReadXml(MyPath + "//UserFriend//" + TabmyFriend.TableName + ".xml"); TabmyFriend.Columns.Add("UserImg", typeof(String)); TabmyFriend.Columns.Add("UserNich", typeof(String)); TabmyFriend.Columns.Add("ZX", typeof(Boolean)); TabmyFriend.Columns.Add("UserIp", typeof(String)); foreach (DataRow myrow in TabmyFriend.Rows) { DataRow[] DataRows = TabUser.Select(" UserName = '" + myrow["UserName"].ToString() + "'"); if (DataRows.Length > 0) { myrow["UserImg"] = DataRows[0]["UserImg"].ToString(); myrow["UserNich"] = DataRows[0]["UserNich"].ToString(); try { myrow["ZX"] = (bool)DataRows[0]["ZX"]; myrow["UserIp"] = DataRows[0]["UserIp"].ToString(); } catch { myrow["ZX"] = false; myrow["UserIp"] = ""; } } } } catch { TabmyFriend.Columns.Add("UserName", typeof(String)); TabmyFriend.Columns.Add("UserImg", typeof(String)); TabmyFriend.Columns.Add("ZX", typeof(Boolean)); TabmyFriend.Columns.Add("UserIp", typeof(String)); } IFormatter format = new BinaryFormatter(); MemoryStream stream = new MemoryStream(); format.Serialize(stream, TabmyFriend); stream.Position = 0; byte[] ret = new byte[_maxPacket]; int count = 0; count = stream.Read(ret, 0, _maxPacket); //先发送响应信号,用户客户机的判断 clientSkt.Send(Encoding.Unicode.GetBytes("cmd::RequestFriendList")); while (count >0) { clientSkt.Send(ret); count = stream.Read(ret, 0, _maxPacket); } //发送结束信号 clientSkt.Send(Encoding.Unicode.GetBytes("Find::RequestFriendListEnd")); stream.Close(); return true ; } private void FormMain_Load(object sender, EventArgs e) { MyPath = Application.StartupPath; Read_User(); ReadTabUserMessage(); _receiveThread = new Thread(new ThreadStart(StartUp)); _receiveThread.Start(); } /// <summary> /// 读取所有用户信息 /// </summary> private void Read_User() { try { TabUser.ReadXml(MyPath + "//User.xml"); } catch { TabUser.TableName = "User"; TabUser.Columns.Add("UserName", typeof(String)); TabUser.Columns.Add("UserPwd", typeof(String)); TabUser.Columns.Add("UserNich", typeof(String)); TabUser.Columns.Add("UserImg", typeof(String)); } TabUser.Columns.Add("ZX", typeof(Boolean)); TabUser.Columns.Add("UserIp", typeof(String)); } /// <summary> /// 新用户上/下线后,更新其好友的(好友列表) /// </summary> /// <param name="UserName"> </param> /// <param name="OnLine"> </param> /// <param name="IpAddress"> </param> private void UpdateFriendList(string UserName, bool OnLine, string IpAddress) { DataTable TabmyFriend = new DataTable(); TabmyFriend.TableName = UserName; string svrlog = null; string []UserInformation = new string[2];//UserName + "$" + IpAddress; UserInformation[0] = UserName; UserInformation[1] = IpAddress; IFormatter format = new BinaryFormatter(); MemoryStream stream = new MemoryStream(); format.Serialize(stream, UserInformation); byte[] ret = stream.ToArray(); stream.Close(); if (OnLine) { svrlog = "cmd::RequestAddFriendList"; } else { svrlog = "cmd::RequestRemoveFriendList"; DataRow[] DataRows = TabUser.Select(" UserName = '" + UserName + "'"); if (DataRows.Length > 0) { DataRows[0]["ZX"] = false; DataRows[0]["UserIp"] = ""; } } try { TabmyFriend.ReadXml(MyPath + "//UserFriend//" + TabmyFriend.TableName + ".xml"); foreach (DataRow myrow in TabmyFriend.Rows) { if(_transmit_tb.ContainsKey(myrow["UserName"].ToString())) { Socket _clientSkt = _transmit_tb[myrow["UserName"].ToString()] as Socket; _clientSkt.Send(Encoding.Unicode.GetBytes(svrlog)); _clientSkt.Send(ret); } } } catch { } } [code=C#][/code /// <summary> /// 线程执行体,转发消息 /// </summary> /// <param name="obj">传递给线程执行体的用户名,用以与用户通信 </param> private void ThreadFunc(object obj) { //通过转发表得到当前用户套接字 Socket clientSkt = _transmit_tb[obj] as Socket; //主循环 while (true) { try { //接受第一个数据包。 //由于程序逻辑结构简单,所以在这里对客户机发送的第一个包内容作逐一判断, //这里的实现不够优雅,但不失为此简单模型的一个解决之道。 byte[] packetBuff = new byte[_maxPacket]; clientSkt.Receive(packetBuff); string _str = Encoding.Unicode.GetString(packetBuff).TrimEnd('/0'); //如果是发给不在线好友的信息 if (_str.StartsWith("cmd::FriendMessage")) { string UserName = _str.Substring("cmd::FriendMessage".Length, 20).Trim(); string MessageS = _str.Substring("cmd::FriendMessage".Length + 20, _str.Length - "cmd::FriendMessage".Length - 20); SaveMessage(obj as string, UserName, MessageS); continue; } //如果是离线请求 if (_str.StartsWith("cmd::RequestLogout")) { _transmit_tb.Remove(obj); UpdateFriendList((string)obj, false, ""); // string svrlog = string.Format("[系统消息]用户 {0} 在 {1} 已断开... 当前在线人数: {2}/r/n/r/n", obj, DateTime.Now, _transmit_tb.Count); // Console.WriteLine(svrlog); //向所有客户机发送系统消息 //foreach (DictionaryEntry de in _transmit_tb) //{ // string _clientName = de.Key as string; // Socket _clientSkt = de.Value as Socket; // _clientSkt.Send(Encoding.Unicode.GetBytes(svrlog)); //} Thread.CurrentThread.Abort(); } //如果是请求好友列表 if (_str.StartsWith("cmd::RequestFriendList")) { SerializeFriendList(obj, clientSkt); // 将该用户不在线时的信息发送给用户 DataTable TabMessage = ReadMessage(obj as string); if (TabMessage != null) { foreach (DataRow myrow in TabMessage.Rows) { if (myrow["SendUserName"].ToString() == "System::Message") { clientSkt.Send(Encoding.Unicode.GetBytes(myrow["Message"].ToString())); } else { clientSkt.Send(Encoding.Unicode.GetBytes("cmd::FriendMessage" + myrow["SendUserName"].ToString().PadRight(20, ' ') + myrow["Message"].ToString())); } } } //这里不需要再继续接受后继数据包了,跳出当前循环体。 continue; } ////如果是请求好友列表 //if (_str.StartsWith("cmd::RequestOnLineList")) //{ // byte[] onlineBuff = SerializeOnlineList(); // //先发送响应信号,用户客户机的判断 // clientSkt.Send(Encoding.Unicode.GetBytes("cmd::RequestOnLineList")); // clientSkt.Send(onlineBuff); // //这里不需要再继续接受后继数据包了,跳出当前循环体。 // continue; //} //查找用户 if (_str.StartsWith("Find::FindFriend")) { DataTable TabFind = TabUser.Clone(); DataRow [] FindRow =null ; string UserName = _str.Substring("Find::FindFriend".Length, _str.Length - "Find::FindFriend".Length); if (UserName.Equals("Find::WhoOnLine")) { //看谁在线 FindRow = TabUser.Select(" ZX = 1"); } else//精确查找 { FindRow = TabUser.Select("UserName = '" + UserName + "'"); } foreach (DataRow myrow in FindRow) { TabFind.ImportRow(myrow); } clientSkt.Send(Encoding.Unicode.GetBytes("Find::FindFriend")); IFormatter format = new BinaryFormatter(); MemoryStream stream = new MemoryStream(); format.Serialize(stream, TabFind); stream.Position = 0; byte[] ret = new byte[_maxPacket]; int count = 0; count = stream.Read(ret, 0, _maxPacket); while (count >0) { clientSkt.Send(ret); count = stream.Read(ret, 0, _maxPacket); } clientSkt.Send(Encoding.Unicode.GetBytes("Find::FindFriendEnd")); stream.Close(); TabFind = null; FindRow = null; //这里不需要再继续接受后继数据包了,跳出当前循环体。 continue; } //请求添加好友 if (_str.StartsWith("Find::AddFriendAsk")) { string UserName = _str.Substring("Find::AddFriendAsk".Length, _str.Length - "Find::AddFriendAsk".Length); //通过转发表查找接收方的套接字 if (_transmit_tb.Count != 0 && _transmit_tb.ContainsKey(UserName)) { Socket receiverSkt = _transmit_tb[UserName] as Socket; receiverSkt.Send(Encoding.Unicode.GetBytes("Find::AddFriendAsk" + obj as string)); } //这里不需要再继续接受后继数据包了,跳出当前循环体。 continue; } //回复答应添加好友 if (_str.StartsWith("Find::AddFriendYes")) { string UserName = _str.Substring("Find::AddFriendYes".Length, _str.Length - "Find::AddFriendYes".Length); //// 保存数据 DataTable TabmyFriend = new DataTable() ; //保存该用户 TabmyFriend.ReadXml(MyPath + "//UserFriend//" + obj as string + ".xml"); DataRow newRow = TabmyFriend.NewRow(); newRow["UserName"] = UserName; TabmyFriend.Rows.Add(newRow); TabmyFriend.WriteXml(MyPath + "//UserFriend//" + obj as string + ".xml", XmlWriteMode.WriteSchema, false); //保存其好友 TabmyFriend = new DataTable(); TabmyFriend.ReadXml(MyPath + "//UserFriend//" + UserName + ".xml"); DataRow newRow1 = TabmyFriend.NewRow(); newRow1["UserName"] = obj as string; TabmyFriend.Rows.Add(newRow1); TabmyFriend.WriteXml(MyPath + "//UserFriend//" + UserName + ".xml", XmlWriteMode.WriteSchema, false); TabmyFriend = null; //更新好友列表 SerializeFriendList(obj, clientSkt); 上面发了服务器端,没发客户端,现在补上!不知道写的好不好,见笑了 C# code public partial class Form1 : Form { private TcpClient client; private bool isExit = false; private NetworkStream networkStream; private EventWaitHandle allDone = new EventWaitHandle(false, EventResetMode.ManualReset); #region 用于一个线程操作另一个线程的控件 private delegate void SetListBoxCallback(string str); private SetListBoxCallback setListBoxCallBack; private delegate void SetRichTextBoxCallback(string str); private SetRichTextBoxCallback setRichTextBoxCallBack; #endregion public Form1() { InitializeComponent(); listBoxStatus.HorizontalScrollbar = true; setListBoxCallBack = new SetListBoxCallback(SetListBox); setRichTextBoxCallBack = new SetRichTextBoxCallback(SetReceiveText); } //状态显示 private void SetListBox(string str) { listBoxStatus.Items.Add(str); listBoxStatus.SelectedIndex = listBoxStatus.Items.Count - 1; listBoxStatus.ClearSelected(); } //接收客户端信息 private void SetReceiveText(string str) { richTextBoxReceive.AppendText(str); } //连接服务器.... private void buttonConnet_Click(object sender, EventArgs e) { client = new TcpClient(AddressFamily.InterNetwork); //得到服务器IP IPAddress ip= IPAddress.Parse("127.0.0.1"); //创建一个委托,并知名在异步操作完成时执行的方法 AsyncCallback callback = new AsyncCallback(RequestCallBack); allDone.Reset(); client.BeginConnect(ip, 7100, RequestCallBack, client); } private void RequestCallBack(IAsyncResult ar) { allDone.Set(); try { client = (TcpClient)ar.AsyncState; client.EndConnect(ar); listBoxStatus.Invoke(setListBoxCallBack, string.Format("与服务器{0}连接成功", client.Client.RemoteEndPoint)); networkStream = client.GetStream(); ReadObject readObject = new ReadObject(networkStream, client.ReceiveBufferSize); networkStream.BeginRead(readObject.bytes, 0, readObject.bytes.Length, ReadCallBack, readObject); } catch (Exception e1) { listBoxStatus.Invoke(setListBoxCallBack, e1.Message); return; } } //异步操作完成时执行的回调调用的方法 private void ReadCallBack(IAsyncResult ar) { try { ReadObject ro = (ReadObject)ar.AsyncState; int count = ro.netStream.EndRead(ar); richTextBoxReceive.Invoke(setRichTextBoxCallBack, System.Text.Encoding.UTF8.GetString(ro.bytes, 0, count)); if (isExit == false) { ro = new ReadObject(networkStream, client.ReceiveBufferSize); networkStream.BeginRead(ro.bytes, 0, ro.bytes.Length, ReadCallBack, ro); } } catch (Exception e2) { listBoxStatus.Invoke(setListBoxCallBack, e2.Message); return; } } //发送数据 private void SendString(string str) { try { byte[] by = System.Text.Encoding.UTF8.GetBytes(str+"/r/n"); networkStream.BeginWrite(by, 0, by.Length, new AsyncCallback(SendCallBack), networkStream); networkStream.Flush(); }catch(Exception e3){ listBoxStatus.Invoke(setListBoxCallBack, e3.Message); return; } } //发送数据回调的方法 private void SendCallBack(IAsyncResult ar) { try { networkStream.EndWrite(ar); } catch (Exception e4) { listBoxStatus.Invoke(setListBoxCallBack, e4.Message); return; } } private void buttonSend_Click(object sender, EventArgs e) { SendString(richTextBoxSend.Text); richTextBoxSend.Clear(); } private void Form1_FormClosing(object sender, FormClosingEventArgs e) { isExit = true; allDone.Set(); } }

你可能感兴趣的:(exception,tcp,socket,String,Stream,C#)