gpt4 book ai didi

c# - 将控制台聊天程序转换为 GUI

转载 作者:太空宇宙 更新时间:2023-11-03 13:52:03 24 4
gpt4 key购买 nike

我在控制台中有一个基本的聊天客户端。这是代码

对于服务器

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 按钮。

但是每个线程都创建自己的流,我认为在不同线程上创建单独的事件处理程序不是一个好主意。

简而言之,我需要一些关于从哪里开始这个项目的建议。

谢谢。

最佳答案

网络很难。您当前的方法只是阅读所有内容并将所有内容视为完整的消息,这种方法很脆弱。它在调试期间有效,但在生产期间会失败,因为 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);
}
}

enter image description here

完整示例可在此处获得:https://github.com/jgauffin/Samples/tree/master/Griffin.Networking/ChatServerClient

更新:

由于这是一个学校项目,而且您不能使用 .NET 以外的任何东西,所以我可能会使用最简单的方法。那就是使用新行 ("\r\n") 作为分隔符。

所以在每一边你只使用了 var chatMessage = streamReader.ReadLine()streamWriter.WriteLine("Chat message");

关于c# - 将控制台聊天程序转换为 GUI,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13433706/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com