[英]C# network - My form(client program) doesn't show when I start server program
I'm developing a networking application. 我正在开发网络应用程序。 The server program gives questions, then clients enters their answers.
服务器程序提出问题,然后客户输入答案。 Actually, both server program and client program were console program.
实际上,服务器程序和客户端程序都是控制台程序。 But, when I changed client program to Form program, It doesn't display.
但是,当我将客户端程序更改为Form程序时,它不会显示。 (ONLY WHEN I TURN ON SERVER PROGRAM!) It works when i don't start server program.
(仅当我打开服务器程序时!)它在我不启动服务器程序时有效。
Here's my server program code, 这是我的服务器程序代码,
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
}
}
}
and here's my client program code, 这是我的客户程序代码,
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++;
}
}
}
How can I solve this problem?? 我怎么解决这个问题?? Thanks for reading my question!
感谢您阅读我的问题!
Since you are already using NetworkStream
, fixing the client code is easy. 由于您已经在使用
NetworkStream
,因此修复客户端代码很容易。 Just switch over to the async
/ await
idiom: 只需切换到
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;
}
}
}
}
Now, that said, you had and still have some other bugs. 就是说,您曾经并且仍然有一些其他错误。 First, your original code had a loop that read from the stream until the return value was 0. All that's going to do is consume the data in the stream without processing any of it.
首先,您的原始代码有一个循环,该循环从流中读取数据, 直到返回值为0。所有要做的就是在不处理任何数据的情况下使用流中的数据。 Very bad.
很坏。 I removed that bug completely in the example above.
我在上面的示例中完全删除了该错误。
Second, you are not checking the return value of the read. 其次,您不检查读取的返回值。 TCP guarantees only one thing: that if you receive any data, the bytes that you receive are in the same order in which they were sent.
TCP仅保证一件事: 如果您接收到任何数据,则接收到的字节将按照其发送的顺序。 In particular, there are no guarantees about how many bytes you'll receive in any given call to
Read()
. 特别是,无法保证在任何给定的
Read()
调用中您将收到多少字节。 If the remote endpoint sends 100 bytes, you could receive all 100 bytes all at once, or you could receive 1 byte at a time in 100 calls to Read()
. 如果远程端点发送了100个字节,则您可以一次全部接收所有100个字节,或者您可以在100次对
Read()
调用中一次接收1个字节。
(Well, actually that's highly unlikely to ever happen...but it's not prohibited by the TCP contract, and in any case if you assume it's true you'll write correct code). (好吧,其实这是非常不可能不会发生......但它不是由TCP合同禁止的,在任何情况下,如果你认为这是真的,你会写正确的代码)。
That's really a whole other question. 这确实是另一个问题。 The above will get your Forms program back to working, in that you'll actually be able to see the
Form
and interact with it. 上面的代码将使您的Forms程序恢复正常工作,因为您实际上将能够看到
Form
并与其进行交互。 And the network code might even seem to work for awhile. 而且网络代码似乎甚至可以工作一段时间。 But eventually you'll get a partial message, or multiple messages combined into one, or some other variation on that theme.
但是最终您会得到部分消息,或者将多条消息组合成一个消息,或者对该主题进行一些其他变化。
When that happens, IMHO one of the easiest ways to fix that in a scenario like yours is to switch to a line-based data scheme. 发生这种情况时,恕我直言,在像您这样的情况下解决此问题的最简单方法之一就是切换到基于行的数据方案。 Ie wrap the
NetworkStream
object in StreamReader
and StreamWriter
objects, and use the ReadLineAsync()
method to receive data instead of the NetworkStream.Read()
method. 即,将
NetworkStream
对象包装在StreamReader
和StreamWriter
对象中,并使用ReadLineAsync()
方法代替NetworkStream.Read()
方法来接收数据。 Regardless, feel free to post another question when you come to that bridge. 无论如何,当您来到那座桥时,随时可以提出另一个问题。 :)
:)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.