TcpClient

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

示例:聊天室

服务端代码


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Threading;
using System.Net;
using System.Net.Sockets;

namespace TestServer
{
    class Program
    {
        static ServerLobby defaultLobby;

        static void Main(string[] args)
        {
            TcpListener server = null;
            try
            {
                Int32 port = 13000;
                IPAddress localAddr = IPAddress.Parse("127.0.0.1");

                server = new TcpListener(localAddr, port);
                server.Start();

                Console.WriteLine("Server started");

                //建立默认大厅
                defaultLobby = new ServerLobby();

                while (true)
                {
                    Console.WriteLine("Waiting for a connection... ");

                    TcpClient client = server.AcceptTcpClient();
                    Console.WriteLine("Connected!");

                    //进入大厅
                    ServerPlayer player = new ServerPlayer(client);
                    defaultLobby.OnEnterServerPlayer(player);

                    ThreadPoolInfo();
                }
            }
            catch (SocketException e)
            {
                Console.WriteLine("SocketException: {0}", e);
            }
            finally
            {
                server.Stop();
            }

            Console.WriteLine("\nHit enter to continue...");
            Console.Read();
        }

        //显示线程池现状
        static void ThreadPoolInfo()
        {
            int a, b;
            ThreadPool.GetAvailableThreads(out a, out b);
            string message = string.Format("CurrentThreadId is : {0}\n" +
                "WorkerThreads is : {1}\nCompletionPortThreads is : {2}\n",
                 Thread.CurrentThread.ManagedThreadId, a.ToString(), b.ToString());

            Console.WriteLine(message);
        }
    }
}

// 大厅,管理所有ServerPlayer
public class ServerLobby
{
    private List<ServerPlayer> playerList = new List<ServerPlayer>();

    // 有玩家进入大厅
    public void OnEnterServerPlayer(ServerPlayer player)
    {
        player.OnEnterLobby(this);
        playerList.Add(player);
    }

    // 有玩家离开大厅
    public void OnLeaveServerPlayer(ServerPlayer player)
    {
        playerList.Remove(player);
        player.OnLeaveLobby();
    }

    // 向大厅中的所有玩家广播消息
    public void BroadcastMessage(string msg)
    {
        for (int i = 0; i < playerList.Count; i++)
        {
            if (playerList[i] == null)
                continue;
            playerList[i].SendMessage(msg);
        }
    }
}

public class ServerPlayer
{
    private TcpClient tcpClient;
    private NetworkStream stream;
    private byte[] receiveBuffer;
    private string clientEndPoint;
    private AsyncCallback mAsyncCallback;
    private ServerLobby mServerLobby;
    private string clientIP;

    public string IP { get { return clientIP; } }

    public ServerPlayer(TcpClient tcpClient)
    {
        this.tcpClient = tcpClient;
        receiveBuffer = new byte[tcpClient.ReceiveBufferSize];
        //显示客户端信息
        clientEndPoint = tcpClient.Client.RemoteEndPoint.ToString();
        clientIP = clientEndPoint;
        Console.WriteLine("Client connected : " + clientEndPoint);

        stream = tcpClient.GetStream();
        mAsyncCallback = new AsyncCallback(ReadCallback);
        stream.BeginRead(receiveBuffer, 0, receiveBuffer.Length, mAsyncCallback, stream);
    }

    void ReadCallback(IAsyncResult result)
    {
        NetworkStream stream = (NetworkStream)result.AsyncState;
        int length = -1;
        try
        {
            //1、TCP中断后length < 1
            //2、TCP中断后产生IOException
            length = stream.EndRead(result);
        }
        catch (IOException ex)
        {
            
        }
        finally
        {
            if (length < 1)//TCP中断了
            {
                Console.WriteLine("client disconnected : " + clientEndPoint);
                //离开大厅
                if (mServerLobby != null)
                    mServerLobby.OnLeaveServerPlayer(this);
            }
        }

        if (length < 1)
            return;


        //显示接收信息
        string message = Encoding.UTF8.GetString(receiveBuffer, 0, length);
        Console.WriteLine("Message: " + message);

        //向大厅中的所有玩家同步消息
        mServerLobby.BroadcastMessage("sync: " + message.Trim() + "\r\n");

        stream.BeginRead(receiveBuffer, 0, receiveBuffer.Length, mAsyncCallback, stream);
    }

    // 发消息
    public void SendMessage(string msg)
    {
        if (!tcpClient.Connected)
            return;

        byte[] bytes = System.Text.Encoding.UTF8.GetBytes(msg);
        stream.Write(bytes, 0, msg.Length);
    }

    // 本玩家进入大厅触发
    public void OnEnterLobby(ServerLobby lobby)
    {
        mServerLobby = lobby;
        //通知大厅中的其他玩家
        mServerLobby.BroadcastMessage(IP + " enter lobby\r\n");
    }

    // 本玩家离开大厅触发
    public void OnLeaveLobby()
    {
        //通知大厅中的其他玩家
        mServerLobby.BroadcastMessage(IP + " leave lobby\r\n");
        mServerLobby = null;
    }
}


客户端代码

MainWindow.xaml

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

MainWindow.xaml.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.IO;
using System.Threading;
using System.Net;
using System.Net.Sockets;
using System.Windows.Threading;//DispatcherTimer

//参考 https://www.cnblogs.com/legion/p/9100347.html
namespace TestClient
{
    /// <summary>
    /// MainWindow.xaml 的交互逻辑
    /// </summary>
    public partial class MainWindow : Window
    {
        public string ChatContent;
        private DispatcherTimer timer;

        byte[] recvData = new byte[1024 * 10];
        TcpClient client = new TcpClient();
        NetworkStream stream = null;

        public MainWindow()
        {
            InitializeComponent();

            timer = new DispatcherTimer();
            timer.Tick += new EventHandler(OnTick);
            timer.Interval = new TimeSpan(0, 0, 1);
            timer.Start();
        }

        private void OnTick(object sender, EventArgs e)
        {
            this.ReceiveTextBlock.Text = ChatContent;
        }

        private void ConnectButton_Click(object sender, RoutedEventArgs e)
        {
            string text = this.IPTextBox.Text;
            string[] arr = text.Split(new char[] { ':' });
            string IP = arr[0];
            int port = int.Parse(arr[1]);
            Connect(IP, port);
        }

        private void Connect(string IP, int port)
        {
            Console.WriteLine("IP={0}, port={1}", IP, port);
            Console.WriteLine("preparing to connect in main thread  " + Thread.CurrentThread.ManagedThreadId);
            client.BeginConnect(IP, port, ConnectCallBack, client);
        }

        private void SendButton_Click(object sender, RoutedEventArgs e)
        {
            string msg = this.InputTextBox.Text;
            this.InputTextBox.Text = string.Empty;
            this.SendMessage(msg);
        }

        private void ConnectCallBack(IAsyncResult result)
        {
            Console.WriteLine("well, i am in the connect thread..." + Thread.CurrentThread.ManagedThreadId);
            TcpClient client = result.AsyncState as TcpClient;
            try
            {
                client.EndConnect(result);
                stream = client.GetStream();
                ChatContent += "connect server successed!\r\n";
            }
            catch (Exception ex)
            {
                Console.WriteLine("well, seems an error occured...");
                Console.WriteLine("which is " + ex.ToString());
                return;
            }
            Console.WriteLine("Hooray, it worked.");
            client.Client.BeginReceive(recvData, 0, recvData.Length, SocketFlags.None, RecvCallBack, client);
        }

        public void RecvCallBack(IAsyncResult result)
        {
            Console.WriteLine("here in recv callback thread.." + Thread.CurrentThread.ManagedThreadId);
            int count = -1;
            try
            {
                count = client.Client.EndReceive(result);
            }
            catch (Exception ex)
            {
                Console.WriteLine("远程计算机关闭");
                return;
            }
            //an recv is done,display it and continue..
            string msg = Encoding.ASCII.GetString(recvData, 0, count);
            Console.WriteLine("your recv this time is:");
            Console.WriteLine(msg);
            ChatContent += msg;
            client.Client.BeginReceive(recvData, 0, recvData.Length, SocketFlags.None, RecvCallBack, client);
        }

        public void SendMessage(string msg)
        {
            if (stream == null)
                return;
            byte[] bytes = Encoding.ASCII.GetBytes(msg);
            stream.Write(bytes, 0, bytes.Length);
            stream.Flush();
        }
    }
}

运行测试

2222.png

1111.png

标签: C#

Powered by emlog  蜀ICP备18021003号-1   sitemap

川公网安备 51019002001593号