使用 BinaryReader/BinaryWriter 建立聊天
Using BinaryReader/BinaryWriter to build a chat
你好,我正在尝试使用 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;
}
}
}
}
}
客户:
using System;
using System.IO;
using System.Net;
using System.Net.Sockets;
namespace tcpClient {
internal class Program {
private static readonly IPAddress s_ipAddress = IPAddress.Parse("127.0.0.1");
private static readonly TcpClient s_client = new TcpClient();
private static void Main(string[] args) {
//Console.WriteLine("Press Enter to start");
//Console.ReadLine();
try {
s_client.Connect(s_ipAddress, 8888);
}
catch (Exception ex) {
Console.WriteLine("{0}", ex.Message);
Console.ReadKey();
return;
}
NetworkStream netStream = s_client.GetStream();
BinaryReader listen = new BinaryReader(netStream);
BinaryWriter send = new BinaryWriter(netStream);
Console.WriteLine("Connected");
Console.Write("Enter name: ");
string name = Console.ReadLine();
send.Write(name);
Console.WriteLine("Chat started");
while (true) {
var message = Console.ReadLine();
send.Write(message);
//Console.WriteLine("{0}: {1}", name, message);
Console.WriteLine(listen.ReadString());
}
}
}
}
您的所有客户端都在 var message = Console.ReadLine();
上被阻止,因此其中 none 继续向下查看是否收到传入消息。
您必须找到一种方法来使用异步 I/O 从控制台读取数据。尽管如此,传入消息可能会在用户键入时到达,在这种情况下,键入的文本将与控制台上的传入消息一起出现乱码。控制台对于聊天应用程序来说不是一个很好的用户界面。
您的代码在客户端和服务器端都有问题。 @Mike Nakis 的回答已经涵盖了前者,现在我将介绍后者。
I have tried adding all clients to a list and running foreach loop on the list to send the message to every connected client, that didn't workout..
我不知道什么没有锻炼,但没有其他方法 - 您必须与连接的客户端保持某种列表。客户端(这里的客户端意味着客户端连接)必须保持对服务器的引用并通知它接收到的消息。服务器会将消息广播给所有当前连接的客户端。
这是您的服务器代码的一个快速而肮脏的版本,它就是这样做的:
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);
}
}
}
和一个快速而肮脏的测试客户端:
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;
}
}
}
你好,我正在尝试使用 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;
}
}
}
}
}
客户:
using System;
using System.IO;
using System.Net;
using System.Net.Sockets;
namespace tcpClient {
internal class Program {
private static readonly IPAddress s_ipAddress = IPAddress.Parse("127.0.0.1");
private static readonly TcpClient s_client = new TcpClient();
private static void Main(string[] args) {
//Console.WriteLine("Press Enter to start");
//Console.ReadLine();
try {
s_client.Connect(s_ipAddress, 8888);
}
catch (Exception ex) {
Console.WriteLine("{0}", ex.Message);
Console.ReadKey();
return;
}
NetworkStream netStream = s_client.GetStream();
BinaryReader listen = new BinaryReader(netStream);
BinaryWriter send = new BinaryWriter(netStream);
Console.WriteLine("Connected");
Console.Write("Enter name: ");
string name = Console.ReadLine();
send.Write(name);
Console.WriteLine("Chat started");
while (true) {
var message = Console.ReadLine();
send.Write(message);
//Console.WriteLine("{0}: {1}", name, message);
Console.WriteLine(listen.ReadString());
}
}
}
}
您的所有客户端都在 var message = Console.ReadLine();
上被阻止,因此其中 none 继续向下查看是否收到传入消息。
您必须找到一种方法来使用异步 I/O 从控制台读取数据。尽管如此,传入消息可能会在用户键入时到达,在这种情况下,键入的文本将与控制台上的传入消息一起出现乱码。控制台对于聊天应用程序来说不是一个很好的用户界面。
您的代码在客户端和服务器端都有问题。 @Mike Nakis 的回答已经涵盖了前者,现在我将介绍后者。
I have tried adding all clients to a list and running foreach loop on the list to send the message to every connected client, that didn't workout..
我不知道什么没有锻炼,但没有其他方法 - 您必须与连接的客户端保持某种列表。客户端(这里的客户端意味着客户端连接)必须保持对服务器的引用并通知它接收到的消息。服务器会将消息广播给所有当前连接的客户端。
这是您的服务器代码的一个快速而肮脏的版本,它就是这样做的:
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);
}
}
}
和一个快速而肮脏的测试客户端:
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;
}
}
}