Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/301.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 使用BinaryReader/BinaryWriter构建聊天室_C#_Tcpclient_Binaryreader_Binarywriter_Server Communication - Fatal编程技术网

C# 使用BinaryReader/BinaryWriter构建聊天室

C# 使用BinaryReader/BinaryWriter构建聊天室,c#,tcpclient,binaryreader,binarywriter,server-communication,C#,Tcpclient,Binaryreader,Binarywriter,Server Communication,您好,我正在尝试使用BinaryReader/BinaryWriter建立聊天,我遇到了一个死胡同,我不知道如何让我的服务器将消息发送到所有连接的客户端 我已尝试将所有客户端添加到列表中,并在列表上运行foreach循环以将消息发送到每个连接的客户端,但没有成功 服务器: using System; using System.IO; using System.Net; using System.Net.Sockets; using System.Threading; namespace ser

您好,我正在尝试使用BinaryReader/BinaryWriter建立聊天,我遇到了一个死胡同,我不知道如何让我的服务器将消息发送到所有连接的客户端

我已尝试将所有客户端添加到列表中,并在列表上运行foreach循环以将消息发送到每个连接的客户端,但没有成功

服务器:

using System;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Threading;

namespace server {
    internal class Program {
        public static int counter = 0;
        //List<Client> clientList = new List <Client>();

        private static readonly IPAddress sr_ipAddress = IPAddress.Parse("127.0.0.1");
        public TcpListener Listener = new TcpListener(sr_ipAddress, 8888);
        public static void Main(string[] args) {
            Program server = new Program();
            server.Start();
            Console.ReadKey();
        }
        public void Start() {
            Listener.Start();
            Console.WriteLine("Server started");
            StartAccept();
        }
        private void StartAccept() {
            Listener.BeginAcceptTcpClient(HandleAsyncConnection, Listener);
        }
        public void HandleAsyncConnection(IAsyncResult res) {
            StartAccept(); //listen for new connections again
            TcpClient clientSocket = Listener.EndAcceptTcpClient(res);
            Client client = new Client(clientSocket);
            client.StartClient();
        }
    }

    internal class Client {
        public TcpClient ClientSocket;
        public string CleintName{get; set;}

        public Client(TcpClient inClientSocket) {
            ClientSocket = inClientSocket;
            NetworkStream netStream = ClientSocket.GetStream();
            BinaryReader Listen = new BinaryReader(netStream);
            CleintName = Listen.ReadString();
        }
        public void StartClient() {
            Thread clientThread = new Thread(Chat);
            clientThread.Start();
            Console.WriteLine("New Client connected {0} => {1}", ClientSocket.GetHashCode(), CleintName);
        }

        private string _message;
        //private string _serverMessage;
        public void Chat() {
            NetworkStream netStream = ClientSocket.GetStream();
            BinaryReader listen = new BinaryReader(netStream);
            BinaryWriter send = new BinaryWriter(netStream);
            while (true) {
                //listening int1
                try {
                    _message = listen.ReadString();
                    Console.WriteLine("{0} :{1}", CleintName, _message);
                    send.Write(CleintName + ": " + _message);
                    //Send.Write(CleintName + " :" + _message);
                }
                catch (Exception ex) {
                    listen.Close();
                    send.Close();
                    netStream.Close();
                    Console.WriteLine(ex.Message);
                    return;
                }
            }
        }
    }
}

您的所有客户端都被阻止在
var message=Console.ReadLine()上
这样,它们都不会继续往下看是否有传入消息到达


您必须找到一种使用异步I/O从控制台读取数据的方法。尽管如此,用户键入时可能会收到传入消息,在这种情况下,键入的文本将与控制台上的传入消息一起被乱码。对于聊天应用程序来说,控制台不是一个很好的用户界面。

您的所有客户端都被阻止在
var message=console.ReadLine()
这样,它们都不会继续往下看是否有传入消息到达


您必须找到一种使用异步I/O从控制台读取数据的方法。尽管如此,用户键入时可能会收到传入消息,在这种情况下,键入的文本将与控制台上的传入消息一起被乱码。对于聊天应用程序来说,控制台不是很好的用户界面。

您的代码在客户端和服务器端都有问题@Mike Nakis的答案已经涵盖了前者,现在我将涵盖后者

我已尝试将所有客户端添加到列表中,并在列表上运行foreach循环以将消息发送到每个连接的客户端,但没有成功

我不知道什么没有锻炼,但没有其他方法-你必须与连接的客户保持某种列表。客户机(这里的客户机指的是客户机连接)必须保持对服务器的引用,并为接收到的消息通知服务器。服务器将向所有当前连接的客户端广播消息

下面是服务器代码的一个快速而肮脏的版本,它可以做到这一点:

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

namespace server
{
    internal class Server
    {
        private static readonly IPAddress sr_ipAddress = IPAddress.Parse("127.0.0.1");
        public static void Main(string[] args)
        {
            Server server = new Server();
            server.Start();
            Console.ReadKey();
        }
        TcpListener Listener = new TcpListener(sr_ipAddress, 8888);
        HashSet<Client> Clients = new HashSet<Client>();
        object syncGate = new object();
        public void Start()
        {
            Listener.Start();
            Console.WriteLine("Server started");
            StartAccept();
        }
        private void StartAccept()
        {
            Listener.BeginAcceptTcpClient(HandleAsyncConnection, Listener);
        }
        private void HandleAsyncConnection(IAsyncResult res)
        {
            StartAccept(); //listen for new connections again
            var clientSocket = Listener.EndAcceptTcpClient(res);
            var client = new Client(this, clientSocket);
            client.StartClient();
            lock (syncGate)
            {
                Clients.Add(client);
                Console.WriteLine("New Client connected {0} => {1}", client.ClientSocket.GetHashCode(), client.ClientName);
            }
        }
        internal void OnDisconnected(Client client)
        {
            lock (syncGate)
            {
                Clients.Remove(client);
                Console.WriteLine("Client disconnected {0} => {1}", client.ClientSocket.GetHashCode(), client.ClientName);
            }
        }
        internal void OnMessageReceived(Client sender, string message)
        {
            lock (syncGate)
            {
                Console.WriteLine("{0}: {1}", sender.ClientName, message);
                foreach (var client in Clients)
                    client.OnMessageReceived(sender, message);
            }
        }
    }

    internal class Client
    {
        public readonly Server Server;
        public TcpClient ClientSocket;
        public string ClientName { get; set; }
        public Client(Server server, TcpClient clientSocket)
        {
            Server = server;
            ClientSocket = clientSocket;
            var netStream = ClientSocket.GetStream();
            var listen = new BinaryReader(netStream);
            ClientName = listen.ReadString();
        }
        public void StartClient()
        {
            var clientThread = new Thread(Chat);
            clientThread.Start();
        }
        private void Chat()
        {
            try
            {
                var netStream = ClientSocket.GetStream();
                var listen = new BinaryReader(netStream);
                while (true)
                {
                    try
                    {
                        var message = listen.ReadString();
                        Server.OnMessageReceived(this, message);
                    }
                    catch (Exception ex)
                    {
                        listen.Close();
                        netStream.Close();
                        Console.WriteLine(ex.Message);
                        return;
                    }
                }
            }
            finally
            {
                Server.OnDisconnected(this);
            }
        }
        internal void OnMessageReceived(Client sender, string message)
        {
            var netStream = ClientSocket.GetStream();
            var send = new BinaryWriter(netStream);
            send.Write(sender.ClientName + ": " + message);
        }
    }
}
使用系统;
使用System.Collections.Generic;
使用System.IO;
Net系统;
使用System.Net.Sockets;
使用系统线程;
命名空间服务器
{
内部类服务器
{
私有静态只读IPAddress sr_IPAddress=IPAddress.Parse(“127.0.0.1”);
公共静态void Main(字符串[]args)
{
服务器=新服务器();
server.Start();
Console.ReadKey();
}
TcpListener侦听器=新的TcpListener(sr_ipAddress,8888);
HashSet Clients=newhashset();
对象同步门=新对象();
公开作废开始()
{
Listener.Start();
Console.WriteLine(“服务器已启动”);
startacept();
}
私有无效StartAccept()
{
BeginAcceptTcpClient(HandleAsyncConnection,Listener);
}
私有无效HandleAsyncConnection(IAsyncResult res)
{
StartAccept();//再次侦听新连接
var clientSocket=Listener.endAcceptCpcClient(res);
var client=new client(这是clientSocket);
client.StartClient();
锁(同步门)
{
客户。添加(客户);
WriteLine(“新客户端连接{0}=>{1}”,Client.ClientSocket.GetHashCode(),Client.ClientName);
}
}
内部无效未断开连接(客户端)
{
锁(同步门)
{
客户。删除(客户);
WriteLine(“客户端断开连接{0}=>{1}”,Client.ClientSocket.GetHashCode(),Client.ClientName);
}
}
消息接收时内部无效(客户端发送方,字符串消息)
{
锁(同步门)
{
Console.WriteLine(“{0}:{1}”,sender.ClientName,message);
foreach(客户机中的var客户机)
客户端.OnMessageReceived(发送方,消息);
}
}
}
内部类客户端
{
公共只读服务器;
公共TcpClient客户端套接字;
公共字符串ClientName{get;set;}
公共客户端(服务器、TcpClient客户端套接字)
{
服务器=服务器;
ClientSocket=ClientSocket;
var netStream=ClientSocket.GetStream();
var listen=新的二进制读取器(netStream);
ClientName=listen.ReadString();
}
public void StartClient()
{
var clientThread=新线程(聊天);
clientThread.Start();
}
私人聊天室()
{
尝试
{
var netStream=ClientSocket.GetStream();
var listen=新的二进制读取器(netStream);
while(true)
{
尝试
{
var message=listen.ReadString();
Server.OnMessageReceived(此,消息);
}
捕获(例外情况除外)
{
听。关闭();
netStream.Close();
控制台写入线(例如消息);
返回;
}
}
}
最后
{
服务器已断开连接(此);
}
}
消息接收时内部无效(客户端发送方,字符串消息)
{
var netStream=ClientSocket.GetStream();
var send=新的二进制编写器(netStream);
send.Write(sender.ClientName+“:”+消息);
}
}
}
和一个快速而肮脏的测试客户端:

using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using System.Windows.Forms;

namespace Samples
{
    static class ChatClient
    {
        [STAThread]
        static void Main()
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            var name = GetChatName();
            if (string.IsNullOrEmpty(name)) return;
            var ipAddress = IPAddress.Parse("127.0.0.1");
            var client = new TcpClient();
            try
            {
                client.Connect(ipAddress, 8888);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
                return;
            }
            var netStream = client.GetStream();
            var send = new BinaryWriter(netStream);
            send.Write(name);
            var form = new Form { Text = "Chat - " + name };
            var tbSend = new TextBox { Dock = DockStyle.Bottom, Parent = form };
            var tbChat = new TextBox { Dock = DockStyle.Fill, Parent = form, Multiline = true, ReadOnly = true };
            var messages = new List<string>();
            tbSend.KeyPress += (_s, _e) =>
            {
                if (_e.KeyChar == 13 && !string.IsNullOrWhiteSpace(tbSend.Text))
                {
                    send.Write(tbSend.Text);
                    tbSend.Text = string.Empty;
                    _e.Handled = true;
                }
            };
            Action<string> onMessageReceived = message =>
            {
                if (messages.Count == 100) messages.RemoveAt(0);
                messages.Add(message);
                tbChat.Lines = messages.ToArray();
            };
            var listener = new Thread(() =>
            {
                var listen = new BinaryReader(netStream);
                while (true)
                {
                    var message = listen.ReadString();
                    form.BeginInvoke(onMessageReceived, message);
                }
            });
            listener.IsBackground = true;
            listener.Start();
            Application.Run(form);
        }
        static string GetChatName()
        {
            var form = new Form { Text = "Enter name:", StartPosition = FormStartPosition.CenterScreen };
            var tb = new TextBox { Parent = form, Top = 8, Left = 8, Width = form.ClientSize.Width - 16, Anchor = AnchorStyles.Left | AnchorStyles.Right | AnchorStyles.Top };
            var okButton = new Button { Parent = form, Text = "OK", DialogResult = DialogResult.OK, Left = 8 };
            var cancelButon = new Button { Parent = form, Text = "Cancel", Left = okButton.Right + 8 };
            okButton.Top = cancelButon.Top = form.ClientSize.Height - okButton.Height - 8;
            okButton.Anchor = cancelButon.Anchor = AnchorStyles.Bottom | AnchorStyles.Left;
            form.AcceptButton = okButton;
            form.CancelButton = cancelButon;
            var dr = form.ShowDialog();
            return dr == DialogResult.OK ? tb.Text : null;
        }
    }
}
使用系统;
使用System.Collections.Generic;
使用System.IO;
Net系统;
使用System.Net.Sockets;
使用Sy
using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using System.Windows.Forms;

namespace Samples
{
    static class ChatClient
    {
        [STAThread]
        static void Main()
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            var name = GetChatName();
            if (string.IsNullOrEmpty(name)) return;
            var ipAddress = IPAddress.Parse("127.0.0.1");
            var client = new TcpClient();
            try
            {
                client.Connect(ipAddress, 8888);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
                return;
            }
            var netStream = client.GetStream();
            var send = new BinaryWriter(netStream);
            send.Write(name);
            var form = new Form { Text = "Chat - " + name };
            var tbSend = new TextBox { Dock = DockStyle.Bottom, Parent = form };
            var tbChat = new TextBox { Dock = DockStyle.Fill, Parent = form, Multiline = true, ReadOnly = true };
            var messages = new List<string>();
            tbSend.KeyPress += (_s, _e) =>
            {
                if (_e.KeyChar == 13 && !string.IsNullOrWhiteSpace(tbSend.Text))
                {
                    send.Write(tbSend.Text);
                    tbSend.Text = string.Empty;
                    _e.Handled = true;
                }
            };
            Action<string> onMessageReceived = message =>
            {
                if (messages.Count == 100) messages.RemoveAt(0);
                messages.Add(message);
                tbChat.Lines = messages.ToArray();
            };
            var listener = new Thread(() =>
            {
                var listen = new BinaryReader(netStream);
                while (true)
                {
                    var message = listen.ReadString();
                    form.BeginInvoke(onMessageReceived, message);
                }
            });
            listener.IsBackground = true;
            listener.Start();
            Application.Run(form);
        }
        static string GetChatName()
        {
            var form = new Form { Text = "Enter name:", StartPosition = FormStartPosition.CenterScreen };
            var tb = new TextBox { Parent = form, Top = 8, Left = 8, Width = form.ClientSize.Width - 16, Anchor = AnchorStyles.Left | AnchorStyles.Right | AnchorStyles.Top };
            var okButton = new Button { Parent = form, Text = "OK", DialogResult = DialogResult.OK, Left = 8 };
            var cancelButon = new Button { Parent = form, Text = "Cancel", Left = okButton.Right + 8 };
            okButton.Top = cancelButon.Top = form.ClientSize.Height - okButton.Height - 8;
            okButton.Anchor = cancelButon.Anchor = AnchorStyles.Bottom | AnchorStyles.Left;
            form.AcceptButton = okButton;
            form.CancelButton = cancelButon;
            var dr = form.ShowDialog();
            return dr == DialogResult.OK ? tb.Text : null;
        }
    }
}