TcpClient

作者:追风剑情 发布于:2019-8-26 11:57 分类:C#

示例:聊天室

服务端代码


  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 ServerLobby defaultLobby;
  15.  
  16. static void Main(string[] args)
  17. {
  18. TcpListener server = null;
  19. try
  20. {
  21. Int32 port = 13000;
  22. IPAddress localAddr = IPAddress.Parse("127.0.0.1");
  23.  
  24. server = new TcpListener(localAddr, port);
  25. server.Start();
  26.  
  27. Console.WriteLine("Server started");
  28.  
  29. //建立默认大厅
  30. defaultLobby = new ServerLobby();
  31.  
  32. while (true)
  33. {
  34. Console.WriteLine("Waiting for a connection... ");
  35.  
  36. TcpClient client = server.AcceptTcpClient();
  37. Console.WriteLine("Connected!");
  38.  
  39. //进入大厅
  40. ServerPlayer player = new ServerPlayer(client);
  41. defaultLobby.OnEnterServerPlayer(player);
  42.  
  43. ThreadPoolInfo();
  44. }
  45. }
  46. catch (SocketException e)
  47. {
  48. Console.WriteLine("SocketException: {0}", e);
  49. }
  50. finally
  51. {
  52. server.Stop();
  53. }
  54.  
  55. Console.WriteLine("\nHit enter to continue...");
  56. Console.Read();
  57. }
  58.  
  59. //显示线程池现状
  60. static void ThreadPoolInfo()
  61. {
  62. int a, b;
  63. ThreadPool.GetAvailableThreads(out a, out b);
  64. string message = string.Format("CurrentThreadId is : {0}\n" +
  65. "WorkerThreads is : {1}\nCompletionPortThreads is : {2}\n",
  66. Thread.CurrentThread.ManagedThreadId, a.ToString(), b.ToString());
  67.  
  68. Console.WriteLine(message);
  69. }
  70. }
  71. }
  72.  
  73. // 大厅,管理所有ServerPlayer
  74. public class ServerLobby
  75. {
  76. private List<ServerPlayer> playerList = new List<ServerPlayer>();
  77.  
  78. // 有玩家进入大厅
  79. public void OnEnterServerPlayer(ServerPlayer player)
  80. {
  81. player.OnEnterLobby(this);
  82. playerList.Add(player);
  83. }
  84.  
  85. // 有玩家离开大厅
  86. public void OnLeaveServerPlayer(ServerPlayer player)
  87. {
  88. playerList.Remove(player);
  89. player.OnLeaveLobby();
  90. }
  91.  
  92. // 向大厅中的所有玩家广播消息
  93. public void BroadcastMessage(string msg)
  94. {
  95. for (int i = 0; i < playerList.Count; i++)
  96. {
  97. if (playerList[i] == null)
  98. continue;
  99. playerList[i].SendMessage(msg);
  100. }
  101. }
  102. }
  103.  
  104. public class ServerPlayer
  105. {
  106. private TcpClient tcpClient;
  107. private NetworkStream stream;
  108. private byte[] receiveBuffer;
  109. private string clientEndPoint;
  110. private AsyncCallback mAsyncCallback;
  111. private ServerLobby mServerLobby;
  112. private string clientIP;
  113.  
  114. public string IP { get { return clientIP; } }
  115.  
  116. public ServerPlayer(TcpClient tcpClient)
  117. {
  118. this.tcpClient = tcpClient;
  119. receiveBuffer = new byte[tcpClient.ReceiveBufferSize];
  120. //显示客户端信息
  121. clientEndPoint = tcpClient.Client.RemoteEndPoint.ToString();
  122. clientIP = clientEndPoint;
  123. Console.WriteLine("Client connected : " + clientEndPoint);
  124.  
  125. stream = tcpClient.GetStream();
  126. mAsyncCallback = new AsyncCallback(ReadCallback);
  127. stream.BeginRead(receiveBuffer, 0, receiveBuffer.Length, mAsyncCallback, stream);
  128. }
  129.  
  130. void ReadCallback(IAsyncResult result)
  131. {
  132. NetworkStream stream = (NetworkStream)result.AsyncState;
  133. int length = -1;
  134. try
  135. {
  136. //1、TCP中断后length < 1
  137. //2、TCP中断后产生IOException
  138. length = stream.EndRead(result);
  139. }
  140. catch (IOException ex)
  141. {
  142. }
  143. finally
  144. {
  145. if (length < 1)//TCP中断了
  146. {
  147. Console.WriteLine("client disconnected : " + clientEndPoint);
  148. //离开大厅
  149. if (mServerLobby != null)
  150. mServerLobby.OnLeaveServerPlayer(this);
  151. }
  152. }
  153.  
  154. if (length < 1)
  155. return;
  156.  
  157.  
  158. //显示接收信息
  159. string message = Encoding.UTF8.GetString(receiveBuffer, 0, length);
  160. Console.WriteLine("Message: " + message);
  161.  
  162. //向大厅中的所有玩家同步消息
  163. mServerLobby.BroadcastMessage("sync: " + message.Trim() + "\r\n");
  164.  
  165. stream.BeginRead(receiveBuffer, 0, receiveBuffer.Length, mAsyncCallback, stream);
  166. }
  167.  
  168. // 发消息
  169. public void SendMessage(string msg)
  170. {
  171. if (!tcpClient.Connected)
  172. return;
  173.  
  174. byte[] bytes = System.Text.Encoding.UTF8.GetBytes(msg);
  175. stream.Write(bytes, 0, msg.Length);
  176. }
  177.  
  178. // 本玩家进入大厅触发
  179. public void OnEnterLobby(ServerLobby lobby)
  180. {
  181. mServerLobby = lobby;
  182. //通知大厅中的其他玩家
  183. mServerLobby.BroadcastMessage(IP + " enter lobby\r\n");
  184. }
  185.  
  186. // 本玩家离开大厅触发
  187. public void OnLeaveLobby()
  188. {
  189. //通知大厅中的其他玩家
  190. mServerLobby.BroadcastMessage(IP + " leave lobby\r\n");
  191. mServerLobby = null;
  192. }
  193. }


客户端代码

MainWindow.xaml

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

MainWindow.xaml.cs

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Threading.Tasks;
  6. using System.Windows;
  7. using System.Windows.Controls;
  8. using System.Windows.Data;
  9. using System.Windows.Documents;
  10. using System.Windows.Input;
  11. using System.Windows.Media;
  12. using System.Windows.Media.Imaging;
  13. using System.Windows.Navigation;
  14. using System.Windows.Shapes;
  15. using System.IO;
  16. using System.Threading;
  17. using System.Net;
  18. using System.Net.Sockets;
  19. using System.Windows.Threading;//DispatcherTimer
  20.  
  21. //参考 https://www.cnblogs.com/legion/p/9100347.html
  22. namespace TestClient
  23. {
  24. /// <summary>
  25. /// MainWindow.xaml 的交互逻辑
  26. /// </summary>
  27. public partial class MainWindow : Window
  28. {
  29. public string ChatContent;
  30. private DispatcherTimer timer;
  31.  
  32. byte[] recvData = new byte[1024 * 10];
  33. TcpClient client = new TcpClient();
  34. NetworkStream stream = null;
  35.  
  36. public MainWindow()
  37. {
  38. InitializeComponent();
  39.  
  40. timer = new DispatcherTimer();
  41. timer.Tick += new EventHandler(OnTick);
  42. timer.Interval = new TimeSpan(0, 0, 1);
  43. timer.Start();
  44. }
  45.  
  46. private void OnTick(object sender, EventArgs e)
  47. {
  48. this.ReceiveTextBlock.Text = ChatContent;
  49. }
  50.  
  51. private void ConnectButton_Click(object sender, RoutedEventArgs e)
  52. {
  53. string text = this.IPTextBox.Text;
  54. string[] arr = text.Split(new char[] { ':' });
  55. string IP = arr[0];
  56. int port = int.Parse(arr[1]);
  57. Connect(IP, port);
  58. }
  59.  
  60. private void Connect(string IP, int port)
  61. {
  62. Console.WriteLine("IP={0}, port={1}", IP, port);
  63. Console.WriteLine("preparing to connect in main thread " + Thread.CurrentThread.ManagedThreadId);
  64. client.BeginConnect(IP, port, ConnectCallBack, client);
  65. }
  66.  
  67. private void SendButton_Click(object sender, RoutedEventArgs e)
  68. {
  69. string msg = this.InputTextBox.Text;
  70. this.InputTextBox.Text = string.Empty;
  71. this.SendMessage(msg);
  72. }
  73.  
  74. private void ConnectCallBack(IAsyncResult result)
  75. {
  76. Console.WriteLine("well, i am in the connect thread..." + Thread.CurrentThread.ManagedThreadId);
  77. TcpClient client = result.AsyncState as TcpClient;
  78. try
  79. {
  80. client.EndConnect(result);
  81. stream = client.GetStream();
  82. ChatContent += "connect server successed!\r\n";
  83. }
  84. catch (Exception ex)
  85. {
  86. Console.WriteLine("well, seems an error occured...");
  87. Console.WriteLine("which is " + ex.ToString());
  88. return;
  89. }
  90. Console.WriteLine("Hooray, it worked.");
  91. client.Client.BeginReceive(recvData, 0, recvData.Length, SocketFlags.None, RecvCallBack, client);
  92. }
  93.  
  94. public void RecvCallBack(IAsyncResult result)
  95. {
  96. Console.WriteLine("here in recv callback thread.." + Thread.CurrentThread.ManagedThreadId);
  97. int count = -1;
  98. try
  99. {
  100. count = client.Client.EndReceive(result);
  101. }
  102. catch (Exception ex)
  103. {
  104. Console.WriteLine("远程计算机关闭");
  105. return;
  106. }
  107. //an recv is done,display it and continue..
  108. string msg = Encoding.ASCII.GetString(recvData, 0, count);
  109. Console.WriteLine("your recv this time is:");
  110. Console.WriteLine(msg);
  111. ChatContent += msg;
  112. client.Client.BeginReceive(recvData, 0, recvData.Length, SocketFlags.None, RecvCallBack, client);
  113. }
  114.  
  115. public void SendMessage(string msg)
  116. {
  117. if (stream == null)
  118. return;
  119. byte[] bytes = Encoding.ASCII.GetBytes(msg);
  120. stream.Write(bytes, 0, bytes.Length);
  121. stream.Flush();
  122. }
  123. }
  124. }

运行测试

2222.png

1111.png

标签: C#

Powered by emlog  蜀ICP备18021003号-1   sitemap

川公网安备 51019002001593号