【发布时间】:2015-02-04 13:12:02
【问题描述】:
上一篇:
客户端打开socket向服务器发送数据:
private void Form1_Load(object sender, EventArgs e)
{
client = new TcpClient();
client.BeginConnect("127.0.0.1", 995, new AsyncCallback(ConnectCallback), client);
}
private void ConnectCallback(IAsyncResult _result) // it will send hello message from client
{
string data;
byte[] remdata = { };
IAsyncResult inResult = _result;
currentProcess = Process.GetCurrentProcess();
string currentProcessAsText = currentProcess.Id.ToString();
SetControlPropertyThreadSafe(proccessIdLabel, "Text", currentProcessAsText);
try {
sock = client.Client;
// send hello message
data = "Client with proccess id " + currentProcessAsText + " is connecting";
sock.Send(Encoding.ASCII.GetBytes(data));
SetControlPropertyThreadSafe(answersTextBox, "Text", answersTextBox.Text + "\n"+ GetCurrentTime() + " Connection established");
}
catch
{
SetControlPropertyThreadSafe(answersTextBox, "Text", answersTextBox.Text + "\n" + GetCurrentTime() + " Can't connect");
}
}
之后我有点击某个按钮(发送消息)的处理程序:
private void SendButton_Click(object sender, EventArgs e)
{
try
{
string data;
sock = client.Client;
data = "Some text";
sock.Send(Encoding.ASCII.GetBytes(data));
}
catch
{
SetControlPropertyThreadSafe(answersTextBox, "Text", "Can't connect");
}
}
同时处理表单关闭发送服务器exit命令,所以他会停止这个客户端的线程:
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
try
{
sock.Send(Encoding.ASCII.GetBytes("exit"));
sock.Close();
}
catch
{
}
}
服务器监听端口并处理消息:
private void Listeners()
{
Socket socketForClient = Listener.AcceptSocket();
string data;
int i = 0;
if (socketForClient.Connected)
{
string remoteHost = socketForClient.RemoteEndPoint.ToString();
Console.WriteLine(Message("Client:" + remoteHost + " now connected to server."));
while (true)
{
// буфер данных
byte[] buf = new byte[1024];
try
{
int messageLength = socketForClient.Receive(buf);
if (messageLength > 0)
{
byte[] cldata = new byte[messageLength];
socketForClient.Receive(cldata);
data = "";
data = Encoding.ASCII.GetString(cldata).Trim();
if (data.Contains("exit"))
{
socketForClient.Close();
string message = Message("Client:" + remoteHost + " is disconnected from the server (client wish).");
Console.WriteLine(message);
return;
}
else
{
Console.WriteLine(Message("Recevied message from client " + remoteHost + ":\n"));
Console.WriteLine(data);
Console.WriteLine("\nEOF\n");
}
}
}
catch
{
string message = Message("Client:" + remoteHost + " is disconnected from the server (forced close).");
Console.WriteLine(message);
socketForClient.Close();
return;
}
}
}
}
private void ServStart()
{
Listener = new TcpListener(LocalPort);
Listener.Start(); // начали слушать
Console.WriteLine("Waiting connections [" + Convert.ToString(LocalPort) + "]...");
for (int i = 0; i < 1000; i++)
{
Thread newThread = new Thread(new ThreadStart(Listeners));
newThread.Start();
}
}
所以在服务器启动时,它会创建 1000 个线程,用于监听客户端消息。
问题:
我将描述一些情况:
- 启动服务器
服务器启动线程并准备接受客户端连接
- 启动客户端
正在建立连接。服务器说客户端连接到某个端口。客户端发送“你好”消息。服务器不处理这条问候消息。
按下按钮,客户端将向服务器发送一些文本。服务器处理这条消息。
按下按钮。客户端再次发送“一些文本”。服务器不处理该消息。
按下按钮。客户端再次发送“一些文本”。服务器处理该消息。
如果我再推,它显然不会处理它......
服务器日志:
为什么服务器接收/客户端只发送 2 条消息中的 1 条?是什么原因造成的?
当客户端表单关闭时,我在向服务器发送exit 消息时也遇到问题。我在此操作上发送 exit 消息。
所以情况:
我只是按下了按钮,服务器处理了它(所以服务器不会处理下一条消息)。
我关闭表单,发送消息,但客户端发送错误消息或服务器接收错误消息。
控制台中的情况:
您可以看到,当表单关闭并且客户端发送exit 时,服务器处理了empty 消息。为什么?
客户端exit命令正常通过服务器时的情况:
- .....
- 客户端发送数据,服务器不处理
- 现在,服务器将处理客户端,所以我们尝试关闭表单:
控制台:
所以在第二个项目中,客户端已经发送了 hello 消息,而服务器未能处理它。在第 3 项中,客户端发送退出命令,服务器正确传递。
主要问题:为什么服务器只处理来自客户端的 2 条消息中的 1 条?
另一点:我还发现,当客户端发送exit 数据时,服务器会收到exit\0\0\0\0\0\0\0\0\(或更多,或更少\0 符号)。为什么?
我认为好消息是,该服务器不断接收或不接收消息。收到 1 条消息,未收到 1 条消息。这说明我缺乏知识,但不是随机错误。
【问题讨论】:
-
你有没有发现为什么你会收到“\0\0\0\0\0\0\0\0\”?我现在遇到这个问题,但只有一个客户端(这让我相信硬件设置很奇怪)。
-
嗯。第一种方法是在服务器端修剪
\0。第二种方式 - 我改变了发送和接收消息的方法,我认为......但我可能会错过一些东西。我不太记得了 -
没问题,谢谢。现在我无论如何都在做同样的事情(告诉服务器忽略'\0')
标签: c# multithreading sockets