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

时间:2012-11-17 18:54:20

标签: c# multithreading sockets networking network-programming

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

对于服务器

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事件处理程序是个好主意。

总之,我需要一些关于从哪个项目开始的建议。

谢谢。

2 个答案:

答案 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);
    }
}

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");

答案 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();
        }