我在控制台中有一个简单的聊天客户端。这是代码
对于服务器
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.IO;
using System.Threading;
namespace chat_server
{
class Program
{
static TcpListener server = new TcpListener(IPAddress.Any, 9999);
static void input(object obs)
{
StreamWriter writer = obs as StreamWriter;
string op = "nothing";
while (!op.Equals("exit"))
{
Console.ResetColor();
Console.WriteLine("This is the " + Thread.CurrentThread.ManagedThreadId);
Console.WriteLine("Enter your text(type exit to quit)");
op = Console.ReadLine();
writer.WriteLine(op);
writer.Flush();
}
}
static void output(Object obs)
{
StreamReader reader = obs as StreamReader;
Console.ForegroundColor = ConsoleColor.Green;
while (true)
{
Console.WriteLine(reader.ReadLine());
}
}
static void monitor()
{
while (true)
{
TcpClient cls = server.AcceptTcpClient();
Thread th = new Thread(new ParameterizedThreadStart(mul_stream));
th.Start(cls);
}
}
static void mul_stream(Object ob)
{
TcpClient client = ob as TcpClient;
Stream streams = client.GetStream();
StreamReader reads = new StreamReader(streams);
StreamWriter writs = new StreamWriter(streams);
new Thread(new ParameterizedThreadStart(output)).Start(reads);
input(writs);
}
static void Main(string[] args)
{
server.Start();
monitor();
server.Stop();
Console.ReadKey();
}
}
}
这是客户端代码
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.IO;
using System.Threading;
namespace chat_client
{
class Program
{
static StreamReader reader;
static StreamWriter writer;
static Thread input_thread;
static void input()
{
string op = "nothing";
while (!op.Equals("exit"))
{
Console.ResetColor();
Console.WriteLine("Enter your text(type exit to quit)");
op = Console.ReadLine();
writer.WriteLine(op);
writer.Flush();
}
}
static void output()
{
Console.ForegroundColor = ConsoleColor.Blue;
while (true)
{
Console.WriteLine(reader.ReadLine());
}
}
static void Main(string[] args)
{
Console.WriteLine("Enter the ip address");
string ip = Console.ReadLine();
TcpClient client = new TcpClient(ip,9999);
NetworkStream stream = client.GetStream();
reader = new StreamReader(stream);
writer = new StreamWriter(stream);
input_thread = new Thread(input);
input_thread.Start();
/*
writer.Write("Hello world");
writer.Flush();
Console.WriteLine("Message Sent");*/
output();
client.Close();
Console.ReadKey();
}
}
}
现在问题是我在将此代码转换为GUI时遇到了一些问题。例如,服务器中通过特定流将消息传递给客户端的输入功能应该与GUI中的SEND按钮等效。
然而,每个线程都创建自己的流,我不认为在不同的线程上创建seprate事件处理程序是个好主意。
总之,我需要一些关于从哪个项目开始的建议。
谢谢。
答案 0 :(得分:1)
网络很难。您当前的方法,即只是阅读所有内容并将所有内容视为完整的消息,都是脆弱的。它在调试期间工作,但在生产期间将失败,因为TCP是基于流的。
相反,您可以使用现有框架抽象出网络层。碰巧,我已经建立了一个开源框架(LGPL)。
在这种情况下,我们只希望能够聊天。所以我添加了这样的聊天消息定义:
public class ChatMessage
{
public DateTime CreatedAt { get; set; }
public string UserName { get; set; }
public string Message { get; set; }
}
该消息放在共享程序集中(由客户端和服务器使用)。
服务器本身的定义如下:
public class ChatServer : IServiceFactory
{
private readonly List<ClientChatConnection> _connectedClients = new List<ClientChatConnection>();
private readonly MessagingServer _server;
public ChatServer()
{
var messageFactory = new BasicMessageFactory();
var configuration = new MessagingServerConfiguration(messageFactory);
_server = new MessagingServer(this, configuration);
}
public IServerService CreateClient(EndPoint remoteEndPoint)
{
var client = new ClientChatConnection(this);
client.Disconnected += OnClientDisconnect;
lock (_connectedClients)
_connectedClients.Add(client);
return client;
}
private void OnClientDisconnect(object sender, EventArgs e)
{
var me = (ClientChatConnection) sender;
me.Disconnected -= OnClientDisconnect;
lock (_connectedClients)
_connectedClients.Remove(me);
}
public void SendToAllButMe(ClientChatConnection me, ChatMessage message)
{
lock (_connectedClients)
{
foreach (var client in _connectedClients)
{
if (client == me)
continue;
client.Send(message);
}
}
}
public void SendToAll(ChatMessage message)
{
lock (_connectedClients)
{
foreach (var client in _connectedClients)
{
client.Send(message);
}
}
}
public void Start()
{
_server.Start(new IPEndPoint(IPAddress.Any, 7652));
}
}
请参阅?在任何地方都没有网络代码。
客户端更容易:
static class Program
{
private static MainForm _mainForm;
private static MessagingClient _client;
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
ConfigureChat();
_mainForm = new MainForm();
Application.Run(_mainForm);
}
private static void ConfigureChat()
{
_client = new MessagingClient(new BasicMessageFactory());
_client.Connect(new IPEndPoint(IPAddress.Loopback, 7652));
_client.Received += OnChatMessage;
}
private static void OnChatMessage(object sender, ReceivedMessageEventArgs e)
{
_mainForm.InvokeIfRequired(() => _mainForm.AddChatMessage((ChatMessage)e.Message));
}
public static void SendChatMessage(ChatMessage msg)
{
if (msg == null) throw new ArgumentNullException("msg");
_client.Send(msg);
}
}
完整示例可在此处找到:https://github.com/jgauffin/Samples/tree/master/Griffin.Networking/ChatServerClient
<强>更新强>
由于这是一个学校项目,你不能使用除.NET以外的任何东西,我可能会使用最简单的方法。这就是使用新行("\r\n"
)作为分隔符。
所以在每一方都使用了var chatMessage = streamReader.ReadLine()
和streamWriter.WriteLine("Chat message");
答案 1 :(得分:0)
//server
public static void Main()
{
try
{
bool status = true;
string forservermessage = "";
string clientmessage = "";
TcpListener tcpListener = new TcpListener(8081);
tcpListener.Start();
Console.WriteLine("Server Started");
Socket socketForClient = tcpListener.AcceptSocket();
Console.WriteLine("Client Connected");
NetworkStream networkStream = new NetworkStream(socketForClient);
StreamWriter streamwriter = new StreamWriter(networkStream);
StreamReader streamreader = new StreamReader(networkStream);
while (status)
{
if (socketForClient.Connected)
{
forservermessage = streamreader.ReadLine();
Console.WriteLine("Client:" + forservermessage);
if (forservermessage == "bye" || forservermessage == "Goodbye" || clientmessage == "bye" ||
clientmessage == "Goodbye" || forservermessage == "Bye" || clientmessage == "Bye")
{
status = false;
streamreader.Close();
networkStream.Close();
streamwriter.Close();
return;
}
Console.Write("Server:");
clientmessage = Console.ReadLine();
streamwriter.WriteLine(clientmessage);
streamwriter.Flush();
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
Console.ReadKey();
//client
public static void Main()
{
TcpClient socketForServer;
bool status = true;
try
{
socketForServer = new TcpClient("localhost", 8081);
Console.WriteLine("Connected to Server");
}
catch
{
Console.WriteLine("Failed to Connect to server{0}:999", "localhost");
Console.ReadKey();
return;
}
NetworkStream networkStream = socketForServer.GetStream();
StreamReader streamreader = new StreamReader(networkStream);
StreamWriter streamwriter = new StreamWriter(networkStream);
try
{
string clientmessage = "";
string forservermessage = "";
while (status)
{
Console.Write("Client:");
clientmessage = Console.ReadLine();
//if ((clientmessage == "bye") || (clientmessage == "BYE"))
//{
// status = false;
// streamwriter.WriteLine("bye");
// streamwriter.Flush();
//}
if ((clientmessage != "bye") && (clientmessage != "BYE"))
{
streamwriter.WriteLine(clientmessage);
streamwriter.Flush();
forservermessage = streamreader.ReadLine();
Console.WriteLine("Server" + forservermessage);
}
}
}
catch
{
Console.WriteLine("Exception reading from the server");
}
streamreader.Close();
networkStream.Close();
streamwriter.Close();
}