一个简易聊天室

作者:追风剑情 发布于:2019-9-16 15:39 分类:C#

一、工程结构

2222.png

配置条件编译: [生成]->[配置管理器]

111111.png

二、代码

UniNetwork.cs


  1. using System;
  2. using System.Collections.Generic;
  3. using System.Net.Sockets;
  4. using System.IO;
  5.  
  6. /// <summary>
  7. /// 网络通信
  8. /// </summary>
  9. public class UniNetwork
  10. {
  11. protected TcpClient mTcpClient = new TcpClient();
  12. protected PackageParser mPackageParser = null;
  13. protected ProtocolData mProtocolData = null;
  14. protected byte[] receiveBuffer;
  15. protected uint num = 1;//自维护
  16.  
  17. protected AsyncCallback mAsyncCallback;
  18. public AsyncCallback OnConnectedCallback;
  19. public Action OnDisconnectedCallback;
  20. public Action<ProtocolData> OnPackageCompleteCallback;
  21. public Action OnInvalidPackageCallback;
  22.  
  23. public UniNetwork()
  24. {
  25. mPackageParser = new PackageParser();
  26. mPackageParser.OnPackageComplete += OnPackageComplete;
  27. mPackageParser.OnInvalidPackage += OnInvalidPackage;
  28. receiveBuffer = new byte[ReceiveBufferSize];
  29. mProtocolData = new ProtocolData();
  30. }
  31.  
  32. public void SetTcpClient(TcpClient tcpClient)
  33. {
  34. mTcpClient = tcpClient;
  35. }
  36. public string clientIP
  37. {
  38. get {
  39. if (mTcpClient == null || !mTcpClient.Connected)
  40. return "";
  41. string IP = mTcpClient.Client.RemoteEndPoint.ToString();
  42. return IP;
  43. }
  44. }
  45.  
  46. // 缓冲区大小
  47. public int ReceiveBufferSize
  48. {
  49. get {
  50. if (mTcpClient == null)
  51. return 0;
  52. return mTcpClient.ReceiveBufferSize;
  53. }
  54. }
  55.  
  56. // 连接
  57. public void Connect(string IP, int port)
  58. {
  59. if (mTcpClient == null || mTcpClient.Connected)
  60. return;
  61. mTcpClient.BeginConnect(IP, port, OnTcpConnected, mTcpClient);
  62. }
  63.  
  64. // 连接返回
  65. private void OnTcpConnected(IAsyncResult result)
  66. {
  67. try
  68. {
  69. mTcpClient.EndConnect(result);
  70. }
  71. catch (Exception ex)
  72. {
  73. Console.WriteLine(ex.ToString());
  74. return;
  75. }
  76.  
  77. OnConnected(result);
  78.  
  79. BeginRead();
  80. }
  81. protected void BeginRead()
  82. {
  83. if (mTcpClient == null || !mTcpClient.Connected)
  84. return;
  85. NetworkStream stream = mTcpClient.GetStream();
  86. mAsyncCallback = new AsyncCallback(OnReadCallback);
  87. stream.BeginRead(receiveBuffer, 0, receiveBuffer.Length, mAsyncCallback, stream);
  88. }
  89.  
  90. private void OnReadCallback(IAsyncResult result)
  91. {
  92. // 关闭变量未使用警告
  93. #pragma warning disable 168
  94. var stream = (NetworkStream)result.AsyncState;
  95. int length = -1;
  96. try
  97. {
  98. //1、TCP中断后length < 1
  99. //2、TCP中断后产生IOException
  100. length = stream.EndRead(result);
  101. }
  102. catch (IOException ex)
  103. {
  104. }
  105. finally
  106. {
  107. }
  108.  
  109. if (length < 1)
  110. {
  111. OnDisconnected();
  112. return;
  113. }
  114.  
  115. this.mPackageParser.Receive(receiveBuffer, 0, length);
  116.  
  117. stream.BeginRead(receiveBuffer, 0, receiveBuffer.Length, mAsyncCallback, stream);
  118. #pragma warning restore 168
  119. }
  120. protected virtual void OnConnected(IAsyncResult result)
  121. {
  122. if (this.OnConnectedCallback != null)
  123. this.OnConnectedCallback(result);
  124. }
  125.  
  126. // TCP链接中断
  127. protected virtual void OnDisconnected()
  128. {
  129. if (OnDisconnectedCallback != null)
  130. OnDisconnectedCallback();
  131. }
  132.  
  133. // 返回数据包
  134. protected virtual void OnPackageComplete(ProtocolData pd)
  135. {
  136. if (OnPackageCompleteCallback != null)
  137. OnPackageCompleteCallback(pd);
  138. }
  139.  
  140. // 返回无效数据包
  141. protected virtual void OnInvalidPackage()
  142. {
  143. if (OnInvalidPackageCallback != null)
  144. OnInvalidPackageCallback();
  145. }
  146.  
  147. // 发消息
  148. public void SendMessage(string msg)
  149. {
  150. WriteBuffer(msg);
  151. SendBuffer(1, 1);
  152. }
  153.  
  154. // 发消息
  155. public void SendMessage(byte[] bytes)
  156. {
  157. WriteBuffer(bytes);
  158. SendBuffer(1, 1);
  159. }
  160. public void WriteBuffer(byte[] bytes)
  161. {
  162. mProtocolData.WriteBytes(bytes);
  163. }
  164. public void WriteBuffer(uint i)
  165. {
  166. mProtocolData.WriteUInt32(i);
  167. }
  168. public void WriteBuffer(ushort i)
  169. {
  170. mProtocolData.WriteUShort(i);
  171. }
  172. public void WriteBuffer(string s)
  173. {
  174. mProtocolData.WriteUTF8String(s);
  175. }
  176. public void SendBuffer(uint type, uint id)
  177. {
  178. SendProtocol(type, id, null);
  179. }
  180.  
  181. /// <summary>
  182. /// 发协议
  183. /// </summary>
  184. /// <param name="type">协议类型,根据具体业务定义</param>
  185. /// <param name="id">协议ID,根据具体业务定义</param>
  186. /// <param name="bytes">内容</param>
  187. public void SendProtocol(uint type, uint id, byte[] bytes)
  188. {
  189. if (mTcpClient == null || !mTcpClient.Connected)
  190. return;
  191.  
  192. NetworkStream stream = mTcpClient.GetStream();
  193. if (stream == null || !stream.CanWrite)
  194. return;
  195.  
  196. if (mProtocolData == null)
  197. this.mProtocolData = new ProtocolData();
  198.  
  199. this.mProtocolData.Num = num;
  200. this.mProtocolData.ProType = type;
  201. this.mProtocolData.ID = id;
  202. this.mProtocolData.WriteBytes(bytes);
  203. byte[] data = this.mProtocolData.EncapsulatePackage();
  204. stream.Write(data, 0, data.Length);
  205.  
  206. num++;
  207. if (num > ProtocolData.MAX_PROTOCOL_NUM)
  208. num = 0;
  209. }
  210. // 释放
  211. public void Dispose()
  212. {
  213. //if (mTcpClient != null)
  214. //mTcpClient.Dispose();
  215. if (mProtocolData != null)
  216. mProtocolData.Dispose();
  217. if (mPackageParser != null)
  218. mPackageParser.Dispose();
  219.  
  220. mTcpClient = null;
  221. mProtocolData = null;
  222. mPackageParser = null;
  223. OnConnectedCallback = null;
  224. OnDisconnectedCallback = null;
  225. OnPackageCompleteCallback = null;
  226. OnInvalidPackageCallback = null;
  227. }
  228. }
  229.  
  230. /// <summary>
  231. /// 数据包解析器
  232. /// </summary>
  233. public class PackageParser
  234. {
  235. private ushort size = 0;
  236. private uint lastNum = 0;
  237. private Stack<byte> receiveBuffer = new Stack<byte>();
  238.  
  239. public Action<ProtocolData> OnPackageComplete;
  240. public Action OnInvalidPackage;
  241.  
  242. public void Receive(byte[] bytes)
  243. {
  244. Receive(bytes, 0, bytes.Length);
  245. }
  246.  
  247. public void Receive(byte[] bytes, int start, int length)
  248. {
  249. if (bytes == null || bytes.Length == 0)
  250. return;
  251. for (int i = start + length - 1; i >= start; i--)
  252. receiveBuffer.Push(bytes[i]);
  253. Parse();
  254. }
  255.  
  256. private void Parse()
  257. {
  258. if (size == 0)
  259. {
  260. //用2个字节表示协议长度
  261. if (receiveBuffer.Count < 2)
  262. return;
  263. //Peek() 返回顶部元素,但不删除
  264. //Pop() 返回顶部元素,并删除
  265. byte[] size_bytes = new byte[] { receiveBuffer.Pop(), receiveBuffer.Pop() };
  266. size = BitConverter.ToUInt16(size_bytes, 0);
  267. }
  268.  
  269. if (receiveBuffer.Count >= size)
  270. {
  271. //从缓冲区中提取出一个数据包
  272. byte[] bytes = new byte[size];
  273. for (int i = 0; i < size; i++)
  274. {
  275. bytes[i] = receiveBuffer.Pop();
  276. }
  277. size = 0;
  278.  
  279. if (OnPackageComplete != null)
  280. {
  281. ProtocolData p = new ProtocolData(bytes);
  282. //验证协议序号是否合法
  283. if (p.ValidateNum(lastNum))
  284. {
  285. lastNum = p.Num;
  286. OnPackageComplete(p);
  287. }
  288. else
  289. {
  290. Console.WriteLine("Invalid protocol serial number. id={0}", p.ID);
  291. if (OnInvalidPackage != null)
  292. OnInvalidPackage();
  293. }
  294. }
  295. }
  296. }
  297.  
  298. public void Dispose()
  299. {
  300. if (receiveBuffer != null)
  301. receiveBuffer.Clear();
  302. receiveBuffer = null;
  303. OnPackageComplete = null;
  304. OnInvalidPackage = null;
  305. }
  306. }
  307.  
  308. /// <summary>
  309. /// 协议数据
  310. /// </summary>
  311. public class ProtocolData
  312. {
  313. //最大协议序号
  314. public const uint MAX_PROTOCOL_NUM = 100000;
  315. private BinaryReader reader;
  316. private BinaryWriter writer;
  317. private BinaryWriter tmpWriter;
  318. //数据包长度
  319. private int length;
  320. //协议序号
  321. private uint num = 0;//从1开始
  322. //协议类型
  323. private uint type = 0;
  324. //协议ID
  325. private uint id = 0;
  326. //内容数据
  327. private byte[] bytes;
  328.  
  329. public ProtocolData()
  330. {
  331. this.writer = new BinaryWriter( new MemoryStream() );
  332. }
  333.  
  334. public ProtocolData(byte[] data)
  335. {
  336. this.length = data.Length;
  337. this.reader = new BinaryReader( new MemoryStream(data) );
  338. this.reader.BaseStream.Position = 0;
  339. this.Parse();
  340. }
  341.  
  342. /// <summary>
  343. /// 验证协议序号是否正确
  344. /// 协议序号必须依次递增(也可以是其他规则),从而避免回放攻击
  345. /// </summary>
  346. /// <param name="lastNum">上一条协议序号</param>
  347. /// <returns></returns>
  348. public bool ValidateNum(uint lastNum)
  349. {
  350. if (num > lastNum && num - lastNum == 1)
  351. return true;
  352. if (num == 0 && lastNum == MAX_PROTOCOL_NUM)
  353. return true;
  354. return false;
  355. }
  356.  
  357. public uint Num
  358. {
  359. get { return num; }
  360. set { num = value; }
  361. }
  362.  
  363. public uint ProType
  364. {
  365. get { return type; }
  366. set { type = value; }
  367. }
  368.  
  369. public uint ID
  370. {
  371. get { return id; }
  372. set { id = value; }
  373. }
  374.  
  375. public byte[] Bytes
  376. {
  377. get { return bytes; }
  378. set { bytes = value; }
  379. }
  380.  
  381. public int ReadInt32()
  382. {
  383. return reader.ReadInt32();
  384. }
  385.  
  386. public uint ReadUInt32()
  387. {
  388. return reader.ReadUInt32();
  389. }
  390.  
  391. public string ReadUTF8String()
  392. {
  393. return reader.ReadString();
  394. }
  395.  
  396. public byte[] ReadBytes(int count)
  397. {
  398. return reader.ReadBytes(count);
  399. }
  400.  
  401. //读取流中所有剩余字节
  402. public byte[] ReadAllBytes()
  403. {
  404. return reader.ReadBytes(this.length);
  405. }
  406. public void WriteUShort(ushort i)
  407. {
  408. writer.Write(i);
  409. }
  410.  
  411. public void WriteUInt32(uint i)
  412. {
  413. writer.Write(i);
  414. }
  415.  
  416. public void WriteBytes(byte[] bytes)
  417. {
  418. if (bytes == null || bytes.Length == 0)
  419. return;
  420. writer.Write(bytes);
  421. }
  422.  
  423. public void WriteUTF8String(string s)
  424. {
  425. writer.Write(s);
  426. }
  427. private void Parse()
  428. {
  429. //解析数据包字段
  430. this.num = reader.ReadUInt32();
  431. this.type = reader.ReadUInt32();
  432. this.id = reader.ReadUInt32();
  433. this.bytes = reader.ReadBytes(this.length);
  434.  
  435. //回写
  436. this.reader.BaseStream.Position = 0;
  437. this.reader.BaseStream.Write(this.bytes, 0, this.bytes.Length);
  438. this.reader.BaseStream.Flush();
  439. this.reader.BaseStream.Position = 0;
  440. }
  441.  
  442. // 取出writer缓冲区中的所有字节
  443. private byte[] PopWriterBytes()
  444. {
  445. //内容长度
  446. ushort size = (ushort)writer.BaseStream.Position;
  447. var data = new byte[size];
  448. writer.BaseStream.Position = 0;
  449. writer.BaseStream.Read(data, 0, size);
  450. writer.BaseStream.SetLength(0);
  451. return data;
  452. }
  453.  
  454. // 封装协议包
  455. public byte[] EncapsulatePackage()
  456. {
  457. if (this.tmpWriter == null)
  458. this.tmpWriter = new BinaryWriter( new MemoryStream() );
  459. tmpWriter.BaseStream.Position = 0;
  460. const ushort head_size = 12;//协议头所占字节数
  461. ushort content_size = (ushort)writer.BaseStream.Length;
  462. ushort size = (ushort)(head_size + content_size);
  463. //写入协议头字段
  464. this.tmpWriter.Write(size);
  465. this.tmpWriter.Write(num);
  466. this.tmpWriter.Write(type);
  467. this.tmpWriter.Write(id);
  468. //写入协议内容
  469. byte[] content = PopWriterBytes();
  470. this.tmpWriter.Write(content);
  471. //转字节数组
  472. size = (ushort)tmpWriter.BaseStream.Length;
  473. var data = new byte[size];
  474. tmpWriter.BaseStream.Position = 0;
  475. tmpWriter.BaseStream.Read(data, 0, size);
  476. tmpWriter.BaseStream.SetLength(0);
  477. return data;
  478. }
  479.  
  480. public void Dispose()
  481. {
  482. this.bytes = null;
  483. if (this.reader != null)
  484. this.reader.Dispose();
  485. if (this.writer != null)
  486. this.writer.Dispose();
  487. }
  488. }


Server端: 

Program.cs


  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.IO;
  6. using System.Threading;
  7. using System.Net;
  8. using System.Net.Sockets;
  9.  
  10. namespace TestServer
  11. {
  12. class Program
  13. {
  14. static TcpListener listener = null;
  15. static ServerLobby defaultLobby;
  16.  
  17. static void Main(string[] args)
  18. {
  19. Int32 port = 13000;
  20. IPAddress localAddr = IPAddress.Parse("127.0.0.1");
  21.  
  22. listener = new TcpListener(localAddr, port);
  23. //false: 允许多个程序监听同一个端口
  24. //listener.ExclusiveAddressUse = false;
  25. //ReuseAddress: 允许将套接字绑定到已在使用中的地址
  26. //listener.Server.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
  27. listener.ExclusiveAddressUse = true;
  28. listener.Start();
  29.  
  30. Console.WriteLine("Server started");
  31. Console.WriteLine("Server IP: {0} Port: {1}", localAddr.ToString(), port);
  32.  
  33. //建立默认大厅
  34. defaultLobby = new ServerLobby();
  35. BeginAcceptTcpClient(listener);
  36.  
  37. Console.Read();
  38. }
  39.  
  40. // 开始监听客户端连接
  41. static void BeginAcceptTcpClient(TcpListener listener)
  42. {
  43. try
  44. {
  45. listener.BeginAcceptTcpClient(new AsyncCallback(OnBeginAcceptTcpClient), listener);
  46. }
  47. catch (SocketException e)
  48. {
  49. Console.WriteLine("SocketException: {0}", e);
  50. }
  51. catch (ObjectDisposedException e)
  52. {
  53. //对已释放的对象执行操作时所引发的异常
  54. Console.WriteLine("ObjectDisposedException: {0}", e);
  55. }
  56. }
  57.  
  58. static void OnBeginAcceptTcpClient(IAsyncResult ar)
  59. {
  60. TcpListener listener = (TcpListener)ar.AsyncState;
  61. TcpClient client = listener.EndAcceptTcpClient(ar);
  62.  
  63. Console.WriteLine("收到TCP连接: IP={0}", client.Client.RemoteEndPoint.ToString());
  64.  
  65. //进入大厅
  66. ServerPlayer player = new ServerPlayer(client);
  67. defaultLobby.OnEnterServerPlayer(player);
  68.  
  69. ThreadPoolInfo();
  70.  
  71. BeginAcceptTcpClient(listener);
  72. }
  73.  
  74. static void Stop()
  75. {
  76. if (listener != null)
  77. listener.Stop();
  78. }
  79.  
  80. //显示线程池现状
  81. static void ThreadPoolInfo()
  82. {
  83. int a, b;
  84. ThreadPool.GetAvailableThreads(out a, out b);
  85. string message = string.Format("CurrentThreadId is : {0}\n" +
  86. "WorkerThreads is : {1}\nCompletionPortThreads is : {2}\n",
  87. Thread.CurrentThread.ManagedThreadId, a.ToString(), b.ToString());
  88.  
  89. Console.WriteLine(message);
  90. }
  91. }
  92. }
  93.  
  94. // 大厅,管理所有ServerPlayer
  95. public class ServerLobby
  96. {
  97. private List<ServerPlayer> playerList = new List<ServerPlayer>();
  98.  
  99. // 有玩家进入大厅
  100. public void OnEnterServerPlayer(ServerPlayer player)
  101. {
  102. player.OnEnterLobby(this);
  103. playerList.Add(player);
  104. }
  105.  
  106. // 有玩家离开大厅
  107. public void OnLeaveServerPlayer(ServerPlayer player)
  108. {
  109. playerList.Remove(player);
  110. player.OnLeaveLobby();
  111. }
  112.  
  113. // 向大厅中的所有玩家广播消息
  114. public void BroadcastMessage(string msg)
  115. {
  116. for (int i = 0; i < playerList.Count; i++)
  117. {
  118. if (playerList[i] == null)
  119. continue;
  120. playerList[i].SendMessage(msg);
  121. }
  122. }
  123. }
  124.  
  125. /// <summary>
  126. ///
  127. /// </summary>
  128. public class ServerPlayer : UniNetwork
  129. {
  130. private ServerLobby mServerLobby;
  131. public string IP { get { return clientIP; } }
  132.  
  133. public ServerPlayer(TcpClient tcpClient)
  134. {
  135. this.SetTcpClient(tcpClient);
  136. this.BeginRead();
  137. }
  138.  
  139. protected override void OnDisconnected()
  140. {
  141. CloseConnect();
  142. }
  143. protected override void OnPackageComplete(ProtocolData pd)
  144. {
  145. string message = pd.ReadUTF8String();
  146. Console.WriteLine("Message: {0}", message);
  147. mServerLobby.BroadcastMessage("sync: " + message + "\r\n");
  148. }
  149. protected override void OnInvalidPackage()
  150. {
  151. SendMessage("Kicked out by the server");
  152. CloseConnect();
  153. }
  154. // 本玩家进入大厅触发
  155. public void OnEnterLobby(ServerLobby lobby)
  156. {
  157. mServerLobby = lobby;
  158. //通知大厅中的其他玩家
  159. mServerLobby.BroadcastMessage(IP + " enter lobby\r\n");
  160. }
  161.  
  162. // 本玩家离开大厅触发
  163. public void OnLeaveLobby()
  164. {
  165. //通知大厅中的其他玩家
  166. mServerLobby.BroadcastMessage(IP + " leave lobby\r\n");
  167. mServerLobby = null;
  168. }
  169.  
  170. // 关闭TCP链接
  171. private void CloseConnect()
  172. {
  173. //离开大厅
  174. if (mServerLobby != null)
  175. mServerLobby.OnLeaveServerPlayer(this);
  176.  
  177. this.Dispose();
  178. }
  179. }


Client端: 

MainWindow.xaml


  1. <Window x:Class="TestClientSD.MainWindow"
  2. xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  3. xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  4. Title="Client" Height="320" Width="300" ResizeMode="NoResize"
  5. >
  6. <Grid>
  7. <TextBox Name="IPTextBox" HorizontalAlignment="Left" Height="23" Margin="9,10,0,0" TextWrapping="Wrap" Text="127.0.0.1:13000" VerticalAlignment="Top" Width="120"/>
  8. <Button Name="ConnectButton" Content="Connect" HorizontalAlignment="Left" Margin="136,11,0,0" VerticalAlignment="Top" Width="75" Click="ConnectButton_Click"/>
  9. <!--聊天内容区域-->
  10. <Border HorizontalAlignment="Center" VerticalAlignment="Center"
  11. Width="269" Height="190" CornerRadius="5"
  12. BorderBrush="Blue" BorderThickness="5" Margin="12,40,12.6,59.4">
  13. <TextBox Name="ReceiveTextBlock" HorizontalAlignment="Left" Margin="3,3,3,3" TextWrapping="Wrap" VerticalAlignment="Top" Height="185" Width="269"/>
  14. </Border>
  15. <!--End-->
  16. <TextBox Name="InputTextBox" HorizontalAlignment="Left" Height="23" Margin="12,248,0,0" TextWrapping="Wrap" Text="TextBox" VerticalAlignment="Top" Width="185"/>
  17. <Button Name="SendButton" Content="Send" HorizontalAlignment="Left" Margin="206,250,0,0" VerticalAlignment="Top" Width="75" Click="SendButton_Click"/>
  18. </Grid>
  19. </Window>


MainWindow.xaml.cs


  1. /*
  2. * 由SharpDevelop创建。
  3. * 用户: Admin
  4. * 日期: 2019/9/11
  5. * 时间: 10:51
  6. *
  7. * 要改变这种模板请点击 工具|选项|代码编写|编辑标准头文件
  8. */
  9. using System;
  10. using System.Collections.Generic;
  11. using System.Linq;
  12. using System.Text;
  13. using System.Threading.Tasks;
  14. using System.Windows;
  15. using System.Windows.Controls;
  16. using System.Windows.Data;
  17. using System.Windows.Documents;
  18. using System.Windows.Input;
  19. using System.Windows.Media;
  20. using System.Windows.Media.Imaging;
  21. using System.Windows.Navigation;
  22. using System.Windows.Shapes;
  23. using System.IO;
  24. using System.Threading;
  25. using System.Net;
  26. using System.Net.Sockets;
  27. using System.Windows.Threading;//DispatcherTimer
  28.  
  29. namespace TestClientSD
  30. {
  31. /// <summary>
  32. /// Interaction logic for MainWindow.xaml
  33. /// </summary>
  34. public partial class MainWindow : Window
  35. {
  36. private readonly UniNetwork network = new UniNetwork();
  37. private DispatcherTimer timer;
  38.  
  39. public string ChatContent;
  40. public MainWindow()
  41. {
  42. InitializeComponent();
  43. network.OnConnectedCallback += OnConnectedCallback;
  44. network.OnDisconnectedCallback += OnDisconnectedCallback;
  45. network.OnPackageCompleteCallback += OnPackageCompleteCallback;
  46.  
  47. timer = new DispatcherTimer();
  48. timer.Tick += new EventHandler(OnTick);
  49. timer.Interval = new TimeSpan(0, 0, 1);
  50. timer.Start();
  51. }
  52. private void OnConnectedCallback(IAsyncResult result)
  53. {
  54. ChatContent += "connect server successed!\r\n";
  55. }
  56. private void OnDisconnectedCallback()
  57. {
  58. ChatContent += "disconnected!\r\n";
  59. }
  60.  
  61. private void OnPackageCompleteCallback(ProtocolData pd)
  62. {
  63. string message = pd.ReadUTF8String();
  64. Console.WriteLine("Message: {0}", message);
  65. ChatContent += message;
  66. }
  67.  
  68. private void OnTick(object sender, EventArgs e)
  69. {
  70. this.ReceiveTextBlock.Text = ChatContent;
  71. this.ReceiveTextBlock.ScrollToEnd();
  72. }
  73.  
  74. private void ConnectButton_Click(object sender, RoutedEventArgs e)
  75. {
  76. string text = this.IPTextBox.Text;
  77. string[] arr = text.Split(new char[] { ':' });
  78. string IP = arr[0];
  79. int port = int.Parse(arr[1]);
  80. Console.WriteLine("IP={0}, port={1}", IP, port);
  81. Console.WriteLine("preparing to connect in main thread " + Thread.CurrentThread.ManagedThreadId);
  82. network.Connect(IP, port);
  83. }
  84.  
  85. private void SendButton_Click(object sender, RoutedEventArgs e)
  86. {
  87. string msg = this.InputTextBox.Text;
  88. this.InputTextBox.Text = string.Empty;
  89. network.SendMessage(msg);
  90. }
  91. }
  92. }


运行测试

1111.png

标签: C#

Powered by emlog  蜀ICP备18021003号-1   sitemap

川公网安备 51019002001593号