C#network - 当我启动服务器程序时,我的表单(客户端程序)没有显示

时间:2014-12-06 13:09:43

标签: c# multithreading forms sockets console

我正在开发网络应用程序。 服务器程序提出问题,然后客户输入他们的答案。 实际上,服务器程序和客户端程序都是控制台程序。 但是,当我将客户端程序更改为Form程序时,它没有显示。 (只有当我打开服务器程序时!) 当我不启动服务器程序时,它可以工作。

这是我的服务器程序代码,

using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;

namespace Server
{
    public class TaskInfo
    {
        public Socket client;
        public int thread_num;              
        public int q_num;                   

        public ManualResetEvent doneEvent;  

        public TaskInfo(Socket c, int n, int q, ManualResetEvent d)
        {
            client = c;
            thread_num = n;
            q_num = q;
            doneEvent = d;
        }
    }

    public class ServerTCP
    {
        static int num_client = 2;
        static bool[] check_co_client = new bool[num_client];
        static int num_co_client = 0;

        static void ClientHandler(Object task_info)
        {
            TaskInfo ti = (TaskInfo)task_info;

            // Casting of object
            Socket client = (Socket)ti.client;
            IPEndPoint endpoint = (IPEndPoint)client.RemoteEndPoint;

            //Console.WriteLine("{0} connected at port {1}", endpoint.Address, endpoint.Port);

            int index = ti.q_num;

            byte[] buffer = new byte[256];
            int byteRecv = 0;
            string message = "";

            string[] questions = new string[5];
            questions[0] = "0. What is 5+6?";
            questions[1] = "1. What is 1+3?";
            questions[2] = "2. What is 5+3?";
            questions[3] = "3. What is 1+1?";
            questions[4] = "4. What is 9-5?";

            string[] answers = new string[5];
            answers[0] = "11";
            answers[1] = "4";
            answers[2] = "8";
            answers[3] = "2";
            answers[4] = "4";

            try
            {
                // Send message to client
                buffer = Encoding.ASCII.GetBytes(questions[index]);
                client.Send(buffer, buffer.Length, SocketFlags.None);

                // Receive data from client
                byteRecv = client.Receive(buffer);
                message = Encoding.ASCII.GetString(buffer, 0, byteRecv);

                if (message == answers[ti.q_num])
                {
                    check_co_client[ti.thread_num] = true;
                }
                else
                {
                    check_co_client[ti.thread_num] = false;
                }

                ti.doneEvent.Set();

            }
            catch (SocketException se)
            {
                Console.WriteLine("{0}: {1} [{2}:{3}]", se.ErrorCode, se.Message, endpoint.Address, endpoint.Port);
            }
            finally
            {
                // Close socket
                //client.Close();
            }
        }

        public static void Main()
        {
            TcpListener listener = null;

            try
            {
                // Create new instance and start listening
                listener = new TcpListener(IPAddress.Any, 8080);
                listener.Start();

                Console.WriteLine("<Waiting for clients connection>");

                // Accept the client connection
                Socket[] client = new Socket[num_client];
                int count = 0;
                while (count < num_client)
                {
                    client[count] = listener.AcceptSocket();
                    count++;
                }

                ManualResetEvent[] doneEvents = new ManualResetEvent[num_client];

                // Start threads
                Thread[] t = new Thread[num_client];

                for (int q_num = 0; q_num < 5; q_num++)
                {
                    for (int i = 0; i < num_client; i++)
                    {
                        doneEvents[i] = new ManualResetEvent(false);
                        TaskInfo ti = new TaskInfo(client[i], i, q_num, doneEvents[i]);

                        t[i] = new Thread(ClientHandler);
                        t[i].Start(ti);

                    }

                    WaitHandle.WaitAll(doneEvents);

                    Thread.Sleep(2000);

                    // count clients who enter correct answer
                    for (int index = 0; index < num_client; index++)
                    {
                        if (check_co_client[index])
                        {
                            num_co_client++;
                        }
                    }
                    Console.WriteLine("number of correct answers: {0}", num_co_client);
                    num_co_client = 0;
                }
            }
            catch (SocketException se)
            {
                Console.WriteLine("Error Code: {0}", se.ErrorCode);
                Console.WriteLine("Message: {0}", se.Message);
            }
            finally
            {
                listener.Stop();
            }

            Console.ReadLine(); // Pause for IDE
        }
    }
}

这是我的客户端程序代码,

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Net;
using System.Net.Sockets;
using System.Threading;

namespace Client_Form
{
    public partial class Client_Form : Form
    {
        TcpClient client = null;
        NetworkStream stream = null;
        int count = 0;

        public Client_Form()
        {
            InitializeComponent();

            Start_Program();

        }

        private void Start_Program()
        {
            try
            {
                // Connect to server
                client = new TcpClient("127.0.0.1", 8080);
                //Console.WriteLine("<Connected to server>");
                textBox.Text = "<Connected to server>";

                stream = client.GetStream();

                byte[] buffer = new byte[256];
                int byteRecv = 0;
                string message = "";

                int q_count = 5;

                while (count < q_count)
                {
                    while ((byteRecv = stream.Read(buffer, 0, buffer.Length)) == 0)
                    {
                        textBox.Text = "Waiting for other client";

                        Thread.Sleep(3000);
                    }

                    // Get data from server
                    //byteRecv = stream.Read(buffer, 0, buffer.Length);
                    message = Encoding.ASCII.GetString(buffer, 0, byteRecv);

                    Co_Game_Question.Text = message;

                }

                // Close stream and connection
                stream.Close();
                client.Close();

                //Console.WriteLine("<Connection closed>");
                textBox.Text = "<Connection closed>";
            }
            catch (SocketException se)
            {
                //Console.WriteLine("Error: {0}", se.SocketErrorCode);
                //Console.WriteLine("Error Code: {0}", se.ErrorCode);
                //Console.WriteLine("Message: {0}", se.Message);
                textBox.Text = "Error Message: " + se.Message;
            }
        }

        private void Btn_Enter_Click(object sender, EventArgs e)
        {
            // Send message to server
            //Console.Write("Answer {0}> ", count);
            //textBox.Text = "Answer " + count + "> ";

            byte[] data = Encoding.ASCII.GetBytes(User_answer_box.Text);
            stream.Write(data, 0, data.Length);

            count++;
        }

    }
}

我该如何解决这个问题? 感谢您阅读我的问题!

1 个答案:

答案 0 :(得分:0)

由于您已经在使用NetworkStream,因此修复客户端代码非常简单。只需切换到async / await成语:

namespace Client_Form
{
    public partial class Client_Form : Form
    {
        TcpClient client = null;
        NetworkStream stream = null;
        int count = 0;

        public Client_Form()
        {
            InitializeComponent();
        }

        protected override void OnLoad(EventArgs e)
        {
            // Handling the network operations after the form loads ensures
            // that the asynchronous operations will come back to the main
            // thread as desired.

            // Ignore returned Task
            var _ = Start_Program();
        }

        private async void Start_Program()
        {
            try
            {
                // Connect to server
                client = await Task.Run(() => new TcpClient("127.0.0.1", 8080));
                textBox.Text = "<Connected to server>";

                stream = client.GetStream();

                byte[] buffer = new byte[256];
                int q_count = 5;

                while (count < q_count)
                {
                    textBox.Text = "Waiting for other client";

                    // Get data from server
                    int byteRecv = await stream.ReadAsync(buffer, 0, buffer.Length);
                    string message = Encoding.ASCII.GetString(buffer, 0, byteRecv);

                    Co_Game_Question.Text = message;

                }

                // Close stream and connection
                stream.Close();
                client.Close();

                textBox.Text = "<Connection closed>";
            }
            catch (SocketException se)
            {
                textBox.Text = "Error Message: " + se.Message;
            }
        }
    }
}

现在,那说,你还有其他一些错误。首先,您的原始代码有一个从流读取的循环,直到返回值为0.所有这一切都将消耗流中的数据而不处理任何数据。很坏。我在上面的示例中完全删除了该错误。

其次,您没有检查读取的返回值。 TCP只保证一件事:如果你收到任何数据,你收到的字节顺序与它们的发送顺序相同。特别是,无法保证Read()的任何给定调用中您将收到多少个字节。如果远程端点发送100个字节,您可以同时接收所有100个字节,或者您可以在100个Read()的调用中一次接收1个字节。

(嗯,实际上高度不太可能发生......但TCP合同并未禁止它,并且无论如何,如果你认为它是真的,你会写出正确的代码)。 / p>

这真的是另一个问题。以上内容将使您的Forms程序恢复正常,因为您实际上可以看到Form并与之交互。网络代码甚至可能似乎工作一段时间。但最终你会得到一个部分信息,或者多个信息合并为一个或该主题的其他变体。

当发生这种情况时,恕我直言,在像你这样的场景中解决这个问题的最简单方法之一是切换到基于行的数据方案。即将NetworkStream对象包装在StreamReaderStreamWriter个对象中,并使用ReadLineAsync()方法接收数据而不是NetworkStream.Read()方法。无论如何,当你来到那座桥时,随意发布另一个问题。 :)

相关问题