C# 在C语言中使用Socket进行通信时遇到的问题#
我希望我没有错过一些愚蠢的事情。我正在开发一个应用程序,它可以在许多手持window的移动计算机和中央服务器之间进行通信。当前的体系结构只允许短消息(最多4096字节),我正在修改应用程序,以便在必要时允许更大的通信。此代码似乎间歇性工作,具体取决于服务器的速度和网络通信速度。我需要找到一种方法使服务器的接收代码更加可靠。它有时工作正常,但有时手持设备会抛出错误“无法将数据写入传输连接。远程主机强制关闭了现有连接。” 手持式传输代码:C# 在C语言中使用Socket进行通信时遇到的问题#,c#,sockets,communication,C#,Sockets,Communication,我希望我没有错过一些愚蠢的事情。我正在开发一个应用程序,它可以在许多手持window的移动计算机和中央服务器之间进行通信。当前的体系结构只允许短消息(最多4096字节),我正在修改应用程序,以便在必要时允许更大的通信。此代码似乎间歇性工作,具体取决于服务器的速度和网络通信速度。我需要找到一种方法使服务器的接收代码更加可靠。它有时工作正常,但有时手持设备会抛出错误“无法将数据写入传输连接。远程主机强制关闭了现有连接。” 手持式传输代码: public bool SendMessage(Networ
public bool SendMessage(NetworkStream ansStream, string asMessage)
{
try
{
Byte[] wBytes = System.Text.Encoding.ASCII.GetBytes(asMessage.ToCharArray());
ansStream.Write(wBytes, 0, wBytes.Length);
return true;
}
catch (Exception E)
{
MessageBox.Show(E.Message, "Network Error");
return false;
}
}
public const int BUFFER_LENGTH = 4096;
public void ProcessMessage(object aClient)
{
TcpClient wClient = (aClient as TcpClient);
try
{
byte[] wBytes = new byte[BUFFER_LENGTH];
StringBuilder wMessage = new StringBuilder();
using (NetworkStream wNetStream = wClient.GetStream())
{
try
{
int wiRead = 0;
int wiTotalBytes = 0;
do
{
wiRead = wNetStream.Read(wBytes, 0, wBytes.Length);
wMessage.AppendFormat("{0}", Encoding.ASCII.GetString(wBytes, 0, wiRead));
wiTotalBytes += wiRead;
// my attempt to ensure entire message is read
if (wNetStream.DataAvailable)
{
Thread.Sleep(1000);
}
} while (wNetStream.DataAvailable);
if (wiTotalBytes > 0)
{
string wsAnswerFile = "";
string wsResult = DoBusinessProcess(wMessage.ToString(), out wsAnswerFile);
if (string.IsNullOrEmpty(wsAnswerFile))
{
wBytes = Encoding.ASCII.GetBytes(wsResult);
wNetStream.Write(wBytes, 0, wBytes.Length);
}
else
{
if (File.Exists(wsAnswerFile))
{
SendFile(wsAnswerFile, wNetStream);
}
}
}
}
catch (Exception E)
{
MessageBox.Show(E.Message, "Network Error");
}
finally
{
if (wNetStream != null)
{
wNetStream.Close();
}
}
}
}
}
服务器端接收代码:
public bool SendMessage(NetworkStream ansStream, string asMessage)
{
try
{
Byte[] wBytes = System.Text.Encoding.ASCII.GetBytes(asMessage.ToCharArray());
ansStream.Write(wBytes, 0, wBytes.Length);
return true;
}
catch (Exception E)
{
MessageBox.Show(E.Message, "Network Error");
return false;
}
}
public const int BUFFER_LENGTH = 4096;
public void ProcessMessage(object aClient)
{
TcpClient wClient = (aClient as TcpClient);
try
{
byte[] wBytes = new byte[BUFFER_LENGTH];
StringBuilder wMessage = new StringBuilder();
using (NetworkStream wNetStream = wClient.GetStream())
{
try
{
int wiRead = 0;
int wiTotalBytes = 0;
do
{
wiRead = wNetStream.Read(wBytes, 0, wBytes.Length);
wMessage.AppendFormat("{0}", Encoding.ASCII.GetString(wBytes, 0, wiRead));
wiTotalBytes += wiRead;
// my attempt to ensure entire message is read
if (wNetStream.DataAvailable)
{
Thread.Sleep(1000);
}
} while (wNetStream.DataAvailable);
if (wiTotalBytes > 0)
{
string wsAnswerFile = "";
string wsResult = DoBusinessProcess(wMessage.ToString(), out wsAnswerFile);
if (string.IsNullOrEmpty(wsAnswerFile))
{
wBytes = Encoding.ASCII.GetBytes(wsResult);
wNetStream.Write(wBytes, 0, wBytes.Length);
}
else
{
if (File.Exists(wsAnswerFile))
{
SendFile(wsAnswerFile, wNetStream);
}
}
}
}
catch (Exception E)
{
MessageBox.Show(E.Message, "Network Error");
}
finally
{
if (wNetStream != null)
{
wNetStream.Close();
}
}
}
}
}
调用ProcessMessage并向其传递TCPClient时,如何初始化这些TCPClient连接?如果在没有多线程的循环中执行,那么可能会得到与前面解释的结果类似的结果。当然,如果不知道客户机侦听循环是如何设置的,我就不能确定 查看此链接: 第二个代码片段显示了一个侦听器循环,它将为每个客户端启动一个新线程。如果您没有为每个客户机启动新线程,如果在您从另一个客户机接收数据时,有一个新的客户机正在尝试连接,它会说服务器无法响应
我希望这有帮助 网络错误很常见,您必须编写代码才能避免它们。。。是否每次要发送消息时都要打开和关闭套接字?否则,我不知道如何识别消息边界。另一方面,有点奇怪,您有一个ProcessMessage方法,但实现仍在使用流…是的,我遗漏了这一部分。客户端是在一个循环中声明的,该循环打开侦听器并将客户端发送到一个新线程。多亏了这些想法,我以后可能会回到这种方法,但我已经对客户端进行了设计,使其以小消息的形式发送数据,而不是一次性发送整个文件。是的,TcpClient在为每个连接创建新线程的循环中初始化。感谢您提供该示例的链接,我将修改我的代码以使用“读取到接收到0字节”模型。这与我自己在谷歌上找到的MSDN答案相符。我已经尝试了这两种方法。。。while(DataAvailable)方法和直到0字节的读取方法以及do。。。while是有效的方法。问题是对于较长的通信,循环与Thread.Sleep(1000)行可靠地工作,我希望能够在没有睡眠的情况下读取所有内容,这会降低对较短请求的响应速度。有没有想过我错过了什么?