採用自帶 TcpClient和TcpListener設計一個Tcp通訊的例子node
只實現了TCP通訊編程
1 /***************************************************** 2 * ProjectName: BenXHSocket 3 * Description: 4 * ClassName: SocketObject 5 * CLRVersion: 4.0.30319.18408 6 * Author: JiYF 7 * NameSpace: BenXHSocket 8 * MachineName: JIYONGFEI 9 * CreateTime: 2017/3/31 12:13:06 10 * UpdatedTime: 2017/3/31 12:13:06 11 *****************************************************/ 12 using System; 13 using System.Collections.Generic; 14 using System.Linq; 15 using System.Text; 16 using System.Net; 17 18 namespace BenXHSocket 19 { 20 /// <summary> 21 /// Socket基礎類 22 /// </summary> 23 public abstract class SocketObject 24 { 25 /// <summary> 26 /// 初始化Socket方法 27 /// </summary> 28 /// <param name="ipAddress"></param> 29 /// <param name="port"></param> 30 public abstract void InitSocket(IPAddress ipAddress,int port); 31 public abstract void InitSocket(string ipAddress,int port); 32 33 /// <summary> 34 /// Socket啓動方法 35 /// </summary> 36 public abstract void Start(); 37 38 /// <summary> 39 /// Sockdet中止方法 40 /// </summary> 41 public abstract void Stop(); 42 43 } 44 }
1 /***************************************************** 2 * ProjectName: BenXHSocket 3 * Description: 4 * ClassName: Sockets 5 * CLRVersion: 4.0.30319.18408 6 * Author: JiYF 7 * NameSpace: BenXHSocket 8 * MachineName: JIYONGFEI 9 * CreateTime: 2017/3/31 12:16:10 10 * UpdatedTime: 2017/3/31 12:16:10 11 *****************************************************/ 12 using System; 13 using System.Collections.Generic; 14 using System.Linq; 15 using System.Text; 16 using System.Net; 17 using System.Net.Sockets; 18 19 namespace BenXHSocket 20 { 21 public class Sockets 22 { 23 /// <summary> 24 /// 接收緩衝區大小8k 25 /// </summary> 26 public byte[] RecBuffer = new byte[8 * 1024]; 27 28 /// <summary> 29 /// 發送緩衝區大小8k 30 /// </summary> 31 public byte[] SendBuffer = new byte[8 * 1024]; 32 33 /// <summary> 34 /// 異步接收後包的大小 35 /// </summary> 36 public int Offset { get;set;} 37 38 /// <summary> 39 /// 當前IP地址,端口號 40 /// </summary> 41 public IPEndPoint Ip { get; set; } 42 /// <summary> 43 /// 客戶端主通訊程序 44 /// </summary> 45 public TcpClient Client { get; set; } 46 /// <summary> 47 /// 承載客戶端Socket的網絡流 48 /// </summary> 49 public NetworkStream nStream { get; set; } 50 51 /// <summary> 52 /// 發生異常時不爲null. 53 /// </summary> 54 public Exception ex { get; set; } 55 56 /// <summary> 57 /// 新客戶端標識.若是推送器發現此標識爲true,那麼認爲是客戶端上線 58 /// 僅服務端有效 59 /// </summary> 60 public bool NewClientFlag { get; set; } 61 62 /// <summary> 63 /// 客戶端退出標識.若是服務端發現此標識爲true,那麼認爲客戶端下線 64 /// 客戶端接收此標識時,認爲客戶端異常. 65 /// </summary> 66 public bool ClientDispose { get; set; } 67 68 /// <summary> 69 /// 空參構造 70 /// </summary> 71 public Sockets() { } 72 73 /// <summary> 74 /// 構造函數 75 /// </summary> 76 /// <param name="ip">ip節點</param> 77 /// <param name="client">TCPClient客戶端</param> 78 /// <param name="ns">NetworkStream </param> 79 public Sockets(IPEndPoint ip,TcpClient client,NetworkStream ns) 80 { 81 this.Ip = ip; 82 this.Client = client; 83 this.nStream = ns; 84 } 85 } 86 }
1 /***************************************************** 2 * ProjectName: BenXHSocket 3 * Description: 4 * ClassName: SocketsHandler 5 * CLRVersion: 4.0.30319.18408 6 * Author: JiYF 7 * NameSpace: BenXHSocket 8 * MachineName: JIYONGFEI 9 * CreateTime: 2017/3/31 13:42:48 10 * UpdatedTime: 2017/3/31 13:42:48 11 *****************************************************/ 12 using System; 13 using System.Collections.Generic; 14 using System.Linq; 15 using System.Text; 16 17 namespace BenXHSocket 18 { 19 /// <summary> 20 /// 推送器 21 /// </summary> 22 /// <param name="sockets"></param> 23 public delegate void PushSockets(Sockets sockets); 24 25 }
1 /***************************************************** 2 * ProjectName: BenXHSocket 3 * Description: 4 * ClassName: TcpServer 5 * CLRVersion: 4.0.30319.18408 6 * Author: JiYF 7 * NameSpace: BenXHSocket 8 * MachineName: JIYONGFEI 9 * CreateTime: 2017/3/31 12:24:08 10 * UpdatedTime: 2017/3/31 12:24:08 11 *****************************************************/ 12 using System; 13 using System.Collections.Generic; 14 using System.Linq; 15 using System.Text; 16 using System.Threading; 17 using System.Net; 18 using System.Net.Sockets; 19 20 namespace BenXHSocket 21 { 22 /// <summary> 23 /// TCPServer類 服務端程序 24 /// </summary> 25 public class BXHTcpServer:SocketObject 26 { 27 private bool IsStop = false; 28 object obj = new object(); 29 public static PushSockets pushSockets; 30 31 /// <summary> 32 /// 信號量 33 /// </summary> 34 private Semaphore semap = new Semaphore(5,5000); 35 36 /// <summary> 37 /// 客戶端列表集合 38 /// </summary> 39 public List<Sockets> ClientList = new List<Sockets>(); 40 41 /// <summary> 42 /// 服務端實例對象 43 /// </summary> 44 public TcpListener Listener; 45 46 /// <summary> 47 /// 當前的ip地址 48 /// </summary> 49 private IPAddress IpAddress; 50 51 /// <summary> 52 /// 初始化消息 53 /// </summary> 54 private string InitMsg = "JiYF笨小孩TCP服務端"; 55 56 /// <summary> 57 /// 監聽的端口 58 /// </summary> 59 private int Port; 60 61 /// <summary> 62 /// 當前ip和端口節點對象 63 /// </summary> 64 private IPEndPoint Ip; 65 66 67 /// <summary> 68 /// 初始化服務器對象 69 /// </summary> 70 /// <param name="ipAddress">IP地址</param> 71 /// <param name="port">端口號</param> 72 public override void InitSocket(IPAddress ipAddress, int port) 73 { 74 this.IpAddress = ipAddress; 75 this.Port = port; 76 this.Listener = new TcpListener(IpAddress,Port); 77 } 78 79 /// <summary> 80 /// 初始化服務器對象 81 /// </summary> 82 /// <param name="ipAddress"></param> 83 /// <param name="port"></param> 84 public override void InitSocket(string ipAddress, int port) 85 { 86 this.IpAddress = IPAddress.Parse(ipAddress); 87 this.Port = port; 88 this.Ip = new IPEndPoint(IpAddress,Port); 89 this.Listener = new TcpListener(IpAddress,Port); 90 } 91 92 /// <summary> 93 /// 服務端啓動監聽,處理連接 94 /// </summary> 95 public override void Start() 96 { 97 try 98 { 99 Listener.Start(); 100 Thread Accth = new Thread(new ThreadStart( 101 delegate 102 { 103 while(true) 104 { 105 if(IsStop != false) 106 { 107 break; 108 } 109 this.GetAcceptTcpClient(); 110 Thread.Sleep(1); 111 } 112 } 113 )); 114 Accth.Start(); 115 } 116 catch(SocketException skex) 117 { 118 Sockets sks = new Sockets(); 119 sks.ex = skex; 120 pushSockets.Invoke(sks); 121 } 122 } 123 124 /// <summary> 125 /// 獲取處理新的連接請求 126 /// </summary> 127 private void GetAcceptTcpClient() 128 { 129 try 130 { 131 if(Listener.Pending()) 132 { 133 semap.WaitOne(); 134 //接收到掛起的客戶端請求連接 135 TcpClient tcpClient = Listener.AcceptTcpClient(); 136 137 //維護處理客戶端隊列 138 Socket socket = tcpClient.Client; 139 NetworkStream stream = new NetworkStream(socket,true); 140 Sockets sks = new Sockets(tcpClient.Client.RemoteEndPoint as IPEndPoint,tcpClient,stream); 141 sks.NewClientFlag = true; 142 143 //推送新的客戶端鏈接信息 144 pushSockets.Invoke(sks); 145 146 //客戶端異步接收數據 147 sks.nStream.BeginRead(sks.RecBuffer,0,sks.RecBuffer.Length,new AsyncCallback(EndReader),sks); 148 149 //加入客戶端隊列 150 this.AddClientList(sks); 151 152 //連接成功後主動向客戶端發送一條消息 153 if(stream.CanWrite) 154 { 155 byte[] buffer = Encoding.UTF8.GetBytes(this.InitMsg); 156 stream.Write(buffer, 0, buffer.Length); 157 } 158 semap.Release(); 159 } 160 } 161 catch 162 { 163 return; 164 } 165 } 166 167 /// <summary> 168 /// 異步接收發送的的信息 169 /// </summary> 170 /// <param name="ir"></param> 171 private void EndReader(IAsyncResult ir) 172 { 173 Sockets sks = ir.AsyncState as Sockets; 174 if (sks != null && Listener != null) 175 { 176 try 177 { 178 if (sks.NewClientFlag || sks.Offset != 0) 179 { 180 sks.NewClientFlag = false; 181 sks.Offset = sks.nStream.EndRead(ir); 182 //推送到UI 183 pushSockets.Invoke(sks); 184 sks.nStream.BeginRead(sks.RecBuffer,0,sks.RecBuffer.Length,new AsyncCallback(EndReader),sks); 185 } 186 } 187 catch(Exception skex) 188 { 189 lock (obj) 190 { 191 ClientList.Remove(sks); 192 Sockets sk = sks; 193 //標記客戶端退出程序 194 sk.ClientDispose = true; 195 sk.ex = skex; 196 //推送至UI 197 pushSockets.Invoke(sks); 198 } 199 } 200 } 201 } 202 203 /// <summary> 204 /// 客戶端加入隊列 205 /// </summary> 206 /// <param name="sk"></param> 207 private void AddClientList(Sockets sk) 208 { 209 lock (obj) 210 { 211 Sockets sockets = ClientList.Find(o => { return o.Ip == sk.Ip; }); 212 if (sockets == null) 213 { 214 ClientList.Add(sk); 215 } 216 else 217 { 218 ClientList.Remove(sockets); 219 ClientList.Add(sk); 220 } 221 } 222 } 223 224 /// <summary> 225 /// 服務端中止監聽 226 /// </summary> 227 public override void Stop() 228 { 229 if (Listener != null) 230 { 231 Listener.Stop(); 232 Listener = null; 233 IsStop = true; 234 pushSockets = null; 235 } 236 } 237 238 /// <summary> 239 /// 向全部在線客戶端發送消息 240 /// </summary> 241 /// <param name="SendData">消息內容</param> 242 public void SendToAll(string SendData) 243 { 244 for (int i = 0; i < ClientList.Count; i++) 245 { 246 SendToClient(ClientList[i].Ip, SendData); 247 } 248 } 249 250 /// <summary> 251 /// 向單獨的一個客戶端發送消息 252 /// </summary> 253 /// <param name="ip"></param> 254 /// <param name="SendData"></param> 255 public void SendToClient(IPEndPoint ip,string SendData) 256 { 257 try 258 { 259 Sockets sks = ClientList.Find(o => { return o.Ip == ip; }); 260 if(sks == null || !sks.Client.Connected) 261 { 262 Sockets ks = new Sockets(); 263 //標識客戶端下線 264 sks.ClientDispose = true; 265 sks.ex = new Exception("客戶端沒有鏈接"); 266 pushSockets.Invoke(sks); 267 } 268 if(sks.Client.Connected) 269 { 270 //獲取當前流進行寫入. 271 NetworkStream nStream = sks.nStream; 272 if (nStream.CanWrite) 273 { 274 byte[] buffer = Encoding.UTF8.GetBytes(SendData); 275 nStream.Write(buffer, 0, buffer.Length); 276 } 277 else 278 { 279 //避免流被關閉,從新從對象中獲取流 280 nStream = sks.Client.GetStream(); 281 if (nStream.CanWrite) 282 { 283 byte[] buffer = Encoding.UTF8.GetBytes(SendData); 284 nStream.Write(buffer, 0, buffer.Length); 285 } 286 else 287 { 288 //若是仍是沒法寫入,那麼認爲客戶端中斷鏈接. 289 ClientList.Remove(sks); 290 Sockets ks = new Sockets(); 291 sks.ClientDispose = true;//若是出現異常,標識客戶端下線 292 sks.ex = new Exception("客戶端無鏈接"); 293 pushSockets.Invoke(sks);//推送至UI 294 295 } 296 } 297 } 298 } 299 catch(Exception skex) 300 { 301 Sockets sks = new Sockets(); 302 sks.ClientDispose = true;//若是出現異常,標識客戶端退出 303 sks.ex = skex; 304 pushSockets.Invoke(sks);//推送至UI 305 } 306 } 307 } 308 }
1 /***************************************************** 2 * ProjectName: BenXHSocket 3 * Description: 4 * ClassName: BxhTcpClient 5 * CLRVersion: 4.0.30319.42000 6 * Author: JiYF 7 * NameSpace: BenXHSocket 8 * MachineName: JIYF_PC 9 * CreateTime: 2017/3/31 20:31:48 10 * UpdatedTime: 2017/3/31 20:31:48 11 *****************************************************/ 12 using System; 13 using System.Collections.Generic; 14 using System.Linq; 15 using System.Text; 16 using System.Net; 17 using System.Net.Sockets; 18 using System.Threading; 19 20 namespace BenXHSocket 21 { 22 public class BXHTcpClient : SocketObject 23 { 24 bool IsClose = false; 25 26 /// <summary> 27 /// 當前管理對象 28 /// </summary> 29 Sockets sk; 30 31 /// <summary> 32 /// 客戶端 33 /// </summary> 34 public TcpClient client; 35 36 /// <summary> 37 /// 當前鏈接服務端地址 38 /// </summary> 39 IPAddress Ipaddress; 40 41 /// <summary> 42 /// 當前鏈接服務端端口號 43 /// </summary> 44 int Port; 45 46 /// <summary> 47 /// 服務端IP+端口 48 /// </summary> 49 IPEndPoint ip; 50 51 /// <summary> 52 /// 發送與接收使用的流 53 /// </summary> 54 NetworkStream nStream; 55 56 57 58 /// <summary> 59 /// 初始化Socket 60 /// </summary> 61 /// <param name="ipaddress"></param> 62 /// <param name="port"></param> 63 public override void InitSocket(string ipaddress, int port) 64 { 65 Ipaddress = IPAddress.Parse(ipaddress); 66 Port = port; 67 ip = new IPEndPoint(Ipaddress, Port); 68 client = new TcpClient(); 69 } 70 71 public static PushSockets pushSockets; 72 public void SendData(string SendData) 73 { 74 try 75 { 76 77 if (client == null || !client.Connected) 78 { 79 Sockets sks = new Sockets(); 80 sks.ex = new Exception("客戶端無鏈接.."); 81 sks.ClientDispose = true; 82 83 pushSockets.Invoke(sks);//推送至UI 84 } 85 if (client.Connected) //若是鏈接則發送 86 { 87 if (nStream == null) 88 { 89 nStream = client.GetStream(); 90 } 91 byte[] buffer = Encoding.UTF8.GetBytes(SendData); 92 nStream.Write(buffer, 0, buffer.Length); 93 } 94 } 95 catch (Exception skex) 96 { 97 Sockets sks = new Sockets(); 98 sks.ex = skex; 99 sks.ClientDispose = true; 100 pushSockets.Invoke(sks);//推送至UI 101 } 102 } 103 /// <summary> 104 /// 初始化Socket 105 /// </summary> 106 /// <param name="ipaddress"></param> 107 /// <param name="port"></param> 108 public override void InitSocket(IPAddress ipaddress, int port) 109 { 110 Ipaddress = ipaddress; 111 Port = port; 112 ip = new IPEndPoint(Ipaddress, Port); 113 client = new TcpClient(); 114 } 115 private void Connect() 116 { 117 client.Connect(ip); 118 nStream = new NetworkStream(client.Client, true); 119 sk = new Sockets(ip, client, nStream); 120 sk.nStream.BeginRead(sk.RecBuffer, 0, sk.RecBuffer.Length, new AsyncCallback(EndReader), sk); 121 } 122 private void EndReader(IAsyncResult ir) 123 { 124 125 Sockets s = ir.AsyncState as Sockets; 126 try 127 { 128 if (s != null) 129 { 130 131 if (IsClose && client == null) 132 { 133 sk.nStream.Close(); 134 sk.nStream.Dispose(); 135 return; 136 } 137 s.Offset = s.nStream.EndRead(ir); 138 pushSockets.Invoke(s);//推送至UI 139 sk.nStream.BeginRead(sk.RecBuffer, 0, sk.RecBuffer.Length, new AsyncCallback(EndReader), sk); 140 } 141 } 142 catch (Exception skex) 143 { 144 Sockets sks = s; 145 sks.ex = skex; 146 sks.ClientDispose = true; 147 pushSockets.Invoke(sks);//推送至UI 148 149 } 150 151 } 152 /// <summary> 153 /// 重寫Start方法,其實就是鏈接服務端 154 /// </summary> 155 public override void Start() 156 { 157 Connect(); 158 } 159 public override void Stop() 160 { 161 Sockets sks = new Sockets(); 162 if (client != null) 163 { 164 client.Client.Shutdown(SocketShutdown.Both); 165 Thread.Sleep(10); 166 client.Close(); 167 IsClose = true; 168 client = null; 169 } 170 else 171 { 172 sks.ex = new Exception("客戶端沒有初始化.!"); 173 } 174 pushSockets.Invoke(sks);//推送至UI 175 } 176 177 } 178 }
1 using System; 2 using System.Collections.Generic; 3 using System.ComponentModel; 4 using System.Data; 5 using System.Drawing; 6 using System.Linq; 7 using System.Text; 8 using System.Windows.Forms; 9 using System.Configuration; 10 using System.Net; 11 using BenXHSocket; 12 using System.Threading; 13 14 namespace BenXHSocketTcpServer 15 { 16 public partial class FrmTCPServer : Form 17 { 18 private static string serverIP; 19 private static int port; 20 object obj = new object(); 21 private int sendInt = 0; 22 private static Dictionary<TreeNode, IPEndPoint> DicTreeIPEndPoint = new Dictionary<TreeNode, IPEndPoint>(); 23 24 public FrmTCPServer() 25 { 26 InitializeComponent(); 27 28 serverIP = ConfigurationManager.AppSettings["ServerIP"]; 29 port = int.Parse(ConfigurationManager.AppSettings["ServerPort"]); 30 Control.CheckForIllegalCrossThreadCalls = false; 31 init(); 32 } 33 34 private void init() 35 { 36 treeViewClientList.Nodes.Clear(); 37 TreeNode tn = new TreeNode(); 38 tn.Name = "ClientList"; 39 tn.Text = "客戶端列表"; 40 tn.ImageIndex = 0; 41 tn.ContextMenuStrip = contextMenuStripClientAll; 42 treeViewClientList.Nodes.Add(tn); 43 DicTreeIPEndPoint.Clear(); 44 45 //自已繪製 46 this.treeViewClientList.DrawMode = TreeViewDrawMode.OwnerDrawText; 47 this.treeViewClientList.DrawNode += new DrawTreeNodeEventHandler(treeViewClientList_DrawNode); 48 } 49 50 private BenXHSocket.BXHTcpServer tcpServer; 51 52 53 /// <summary> 54 /// 繪製顏色 55 /// </summary> 56 /// <param name="sender"></param> 57 /// <param name="e"></param> 58 private void treeViewClientList_DrawNode(object sender, DrawTreeNodeEventArgs e) 59 { 60 e.DrawDefault = true; //我這裏用默認顏色便可,只須要在TreeView失去焦點時選中節點仍然突顯 61 return; 62 //or 自定義顏色 63 if ((e.State & TreeNodeStates.Selected) != 0) 64 { 65 //演示爲綠底白字 66 e.Graphics.FillRectangle(Brushes.DarkBlue, e.Node.Bounds); 67 68 Font nodeFont = e.Node.NodeFont; 69 if (nodeFont == null) nodeFont = ((TreeView)sender).Font; 70 e.Graphics.DrawString(e.Node.Text, nodeFont, Brushes.White, Rectangle.Inflate(e.Bounds, 2, 0)); 71 } 72 else 73 { 74 e.DrawDefault = true; 75 } 76 77 if ((e.State & TreeNodeStates.Focused) != 0) 78 { 79 using (Pen focusPen = new Pen(Color.Black)) 80 { 81 focusPen.DashStyle = System.Drawing.Drawing2D.DashStyle.Dot; 82 Rectangle focusBounds = e.Node.Bounds; 83 focusBounds.Size = new Size(focusBounds.Width - 1, 84 focusBounds.Height - 1); 85 e.Graphics.DrawRectangle(focusPen, focusBounds); 86 } 87 } 88 89 } 90 91 /// <summary> 92 /// 開啓服務 93 /// </summary> 94 /// <param name="sender"></param> 95 /// <param name="e"></param> 96 private void StartServerToolStripMenuItem_Click(object sender, EventArgs e) 97 { 98 try 99 { 100 if (serverIP != null && serverIP != "" && port != null && port >= 0) 101 { 102 tcpServer.InitSocket(IPAddress.Parse(serverIP), port); 103 tcpServer.Start(); 104 listBoxServerInfo.Items.Add(string.Format("{0}服務端程序監聽啓動成功!監聽:{1}:{2}",DateTime.Now.ToString(), serverIP, port.ToString())); 105 StartServerToolStripMenuItem.Enabled = false; 106 } 107 108 109 } 110 catch(Exception ex) 111 { 112 listBoxServerInfo.Items.Add(string.Format("服務器啓動失敗!緣由:{0}",ex.Message)); 113 StartServerToolStripMenuItem.Enabled = true; 114 } 115 } 116 117 /// <summary> 118 /// 中止服務監聽 119 /// </summary> 120 /// <param name="sender"></param> 121 /// <param name="e"></param> 122 private void StopServerToolStripMenuItem_Click(object sender, EventArgs e) 123 { 124 tcpServer.Stop(); 125 listBoxServerInfo.Items.Add("服務器程序中止成功!"); 126 StartServerToolStripMenuItem.Enabled = true; 127 128 } 129 130 private void FrmTCPServer_Load(object sender, EventArgs e) 131 { 132 if(tcpServer ==null) 133 listBoxServerInfo.Items.Add(string.Format("服務端監聽程序還沒有開啓!{0}:{1}",serverIP,port)); 134 treeViewClientList.ExpandAll(); 135 BXHTcpServer.pushSockets = new PushSockets(Rev); 136 tcpServer = new BXHTcpServer(); 137 } 138 139 /// <summary> 140 /// 處理接收到客戶端的請求和數據 141 /// </summary> 142 /// <param name="sks"></param> 143 private void Rev(BenXHSocket.Sockets sks) 144 { 145 this.Invoke(new ThreadStart( 146 delegate 147 { 148 if (treeViewClientList.Nodes[0] != null) 149 { 150 151 } 152 153 if (sks.ex != null) 154 { 155 if (sks.ClientDispose) 156 { 157 listBoxServerInfo.Items.Add(string.Format("{0}客戶端:{1}下線!",DateTime.Now.ToString(), sks.Ip)); 158 if (treeViewClientList.Nodes[0].Nodes.ContainsKey(sks.Ip.ToString())) 159 { 160 if (DicTreeIPEndPoint.Count != 0) 161 { 162 removTreeIPEndPoint(sks.Ip); 163 treeViewClientList.Nodes[0].Nodes.RemoveByKey(sks.Ip.ToString()); 164 165 toolStripStatusLabelClientNum.Text = (int.Parse(toolStripStatusLabelClientNum.Text) - 1).ToString();//treeViewClientList.Nodes[0].Nodes.Count.ToString(); 166 167 } 168 169 } 170 } 171 listBoxServerInfo.Items.Add(sks.ex.Message); 172 } 173 else 174 { 175 if (sks.NewClientFlag) 176 { 177 listBoxServerInfo.Items.Add(string.Format("{0}新的客戶端:{0}連接成功",DateTime.Now.ToString(), sks.Ip)); 178 179 TreeNode tn = new TreeNode(); 180 tn.Name = sks.Ip.ToString(); 181 tn.Text = sks.Ip.ToString(); 182 tn.ContextMenuStrip = contextMenuStripClientSingle; 183 tn.Tag = "客戶端"; 184 tn.ImageIndex = 1; 185 186 treeViewClientList.Nodes[0].Nodes.Add(tn); 187 188 //treeview節點和IPEndPoint綁定 189 DicTreeIPEndPoint.Add(tn,sks.Ip); 190 191 if (treeViewClientList.Nodes[0].Nodes.Count > 0) 192 { 193 treeViewClientList.ExpandAll(); 194 } 195 toolStripStatusLabelClientNum.Text = (int.Parse(toolStripStatusLabelClientNum.Text)+1).ToString(); 196 } 197 else if (sks.Offset == 0) 198 { 199 listBoxServerInfo.Items.Add(string.Format("{0}客戶端:{1}下線.!",DateTime.Now.ToString(), sks.Ip)); 200 if (treeViewClientList.Nodes[0].Nodes.ContainsKey(sks.Ip.ToString())) 201 { 202 if (DicTreeIPEndPoint.Count != 0) 203 { 204 removTreeIPEndPoint(sks.Ip); 205 treeViewClientList.Nodes[0].Nodes.RemoveByKey(sks.Ip.ToString()); 206 207 toolStripStatusLabelClientNum.Text = (int.Parse(toolStripStatusLabelClientNum.Text) - 1).ToString(); 208 209 } 210 } 211 } 212 else 213 { 214 byte[] buffer = new byte[sks.Offset]; 215 Array.Copy(sks.RecBuffer, buffer, sks.Offset); 216 string str = Encoding.UTF8.GetString(buffer); 217 listBox1.Items.Add(string.Format("{0}客戶端{1}發來消息:{2}",DateTime.Now.ToString(), sks.Ip, str)); 218 } 219 } 220 } 221 ) 222 ); 223 } 224 225 /// <summary> 226 /// 關閉程序錢中止服務器實例 227 /// </summary> 228 /// <param name="sender"></param> 229 /// <param name="e"></param> 230 private void FrmTCPServer_FormClosing(object sender, FormClosingEventArgs e) 231 { 232 tcpServer.Stop(); 233 } 234 235 private void treeViewClientList_AfterSelect(object sender, TreeViewEventArgs e) 236 { 237 // 238 } 239 240 private void treeViewClientList_MouseClick(object sender, MouseEventArgs e) 241 { 242 if (e.Button == MouseButtons.Right) 243 { 244 treeViewClientList.Focus(); 245 treeViewClientList.SelectedNode = treeViewClientList.GetNodeAt(e.X,e.Y); 246 } 247 248 } 249 250 251 private void toolStripMenuSendSingle_Click(object sender, EventArgs e) 252 { 253 if (treeViewClientList.SelectedNode != null) 254 { 255 tcpServer.SendToClient(DicTreeIPEndPoint[treeViewClientList.SelectedNode], string.Format("服務端單個消息...{0}", sendInt.ToString())); 256 sendInt++; 257 } 258 } 259 260 private void toolStripMenuSendAll_Click(object sender, EventArgs e) 261 { 262 tcpServer.SendToAll("服務端所有發送消息..." + sendInt); 263 sendInt++; 264 } 265 266 private void removTreeIPEndPoint(IPEndPoint ipendPoint) 267 { 268 269 if (DicTreeIPEndPoint.Count <= 0) return; 270 //foreach遍歷Dictionary時候不能對字典進行Remove 271 TreeNode[] keys = new TreeNode[DicTreeIPEndPoint.Count]; 272 DicTreeIPEndPoint.Keys.CopyTo(keys,0); 273 lock (obj) 274 { 275 foreach (TreeNode item in keys) 276 { 277 if (DicTreeIPEndPoint[item] == ipendPoint) 278 { 279 DicTreeIPEndPoint.Remove(item); 280 } 281 } 282 } 283 } 284 285 } 286 }
1 using System; 2 using System.Collections.Generic; 3 using System.ComponentModel; 4 using System.Data; 5 using System.Drawing; 6 using System.Linq; 7 using System.Text; 8 using System.Windows.Forms; 9 using System.Net; 10 using System.Net.Sockets; 11 using BenXHSocket; 12 using System.Threading; 13 14 namespace BenXHSocketClient 15 { 16 public partial class FrmTCPClient : Form 17 { 18 BXHTcpClient tcpClient; 19 20 string ip = string.Empty; 21 string port = string.Empty; 22 private int sendInt = 0; 23 public FrmTCPClient() 24 { 25 InitializeComponent(); 26 Control.CheckForIllegalCrossThreadCalls = false; 27 } 28 29 private void btnConnServer_Click(object sender, EventArgs e) 30 { 31 try 32 { 33 this.ip = txtServerIP.Text.Trim(); 34 this.port = txtServerPort.Text.Trim(); 35 36 tcpClient.InitSocket(ip, int.Parse(port)); 37 tcpClient.Start(); 38 listBoxStates.Items.Add("鏈接成功!"); 39 btnConnServer.Enabled = false; 40 41 } 42 catch (Exception ex) 43 { 44 45 listBoxStates.Items.Add(string.Format("鏈接失敗!緣由:{0}", ex.Message)); 46 btnConnServer.Enabled = true; 47 } 48 } 49 50 private void FrmTCPClient_Load(object sender, EventArgs e) 51 { 52 //客戶端如何處理異常等信息參照服務端 53 54 BXHTcpClient.pushSockets = new PushSockets(Rec); 55 56 tcpClient = new BXHTcpClient(); 57 this.ip = txtServerIP.Text.Trim(); 58 this.port = txtServerPort.Text.Trim(); 59 60 } 61 62 /// <summary> 63 /// 處理推送過來的消息 64 /// </summary> 65 /// <param name="rec"></param> 66 private void Rec(BenXHSocket.Sockets sks) 67 { 68 this.Invoke(new ThreadStart(delegate 69 { 70 if (listBoxText.Items.Count > 1000) 71 { 72 listBoxText.Items.Clear(); 73 } 74 if (sks.ex != null) 75 { 76 if (sks.ClientDispose == true) 77 { 78 //因爲未知緣由引起異常.致使客戶端下線. 好比網絡故障.或服務器斷開鏈接. 79 listBoxStates.Items.Add(string.Format("客戶端下線.!")); 80 } 81 listBoxStates.Items.Add(string.Format("異常消息:{0}", sks.ex)); 82 } 83 else if (sks.Offset == 0) 84 { 85 //客戶端主動下線 86 listBoxStates.Items.Add(string.Format("客戶端下線.!")); 87 } 88 else 89 { 90 byte[] buffer = new byte[sks.Offset]; 91 Array.Copy(sks.RecBuffer, buffer, sks.Offset); 92 string str = Encoding.UTF8.GetString(buffer); 93 listBoxText.Items.Add(string.Format("服務端{0}發來消息:{1}", sks.Ip, str)); 94 } 95 })); 96 } 97 98 private void btnDisConn_Click(object sender, EventArgs e) 99 { 100 tcpClient.Stop(); 101 btnConnServer.Enabled = true; 102 } 103 104 private void btnSendData_Click(object sender, EventArgs e) 105 { 106 tcpClient.SendData("客戶端消息!" + sendInt); 107 sendInt++; 108 109 } 110 111 private void btnConnTest_Click(object sender, EventArgs e) 112 { 113 ThreadPool.QueueUserWorkItem(o => 114 { 115 for (int i = 0; i < 100; i++) 116 { 117 BenXHSocket.BXHTcpClient clientx= new BenXHSocket.BXHTcpClient();//初始化類庫 118 clientx.InitSocket(ip, int.Parse(port)); 119 clientx.Start(); 120 } 121 MessageBox.Show("完成.!"); 122 }); 123 } 124 125 126 } 127 }
BenXHSocket.dll 主要程序動態庫服務器
BenXHSocketClient.exe 客戶端應用程序網絡
BenXHSocketTcpServer.exe 服務端應用程序異步
BenXHSocketTcpServer.exe.config 服務端應用程序配置文件socket
其中:BenXHSocketTcpServer.exe.config爲配置文件,能夠設置監聽的ip地址和端口號,默認ip地址:127.0.0.1 默認的端口號:4455tcp