- 我有一个TCP服务器,它只为客户端发送到服务器的某些消息将数据写回客户端。
-
它基本上是一个基于命令的服务器,服务器只对某些命令使用字符串进行响应,否则不会将任何内容发送回客户端。
-
下面给出的代码是一种方法,它假设如果服务器发送任何数据,它将其显示为"来自服务器的消息",并附加了发送的数据。
class TcpEchoClient { static void Main(string[] args) { Console.WriteLine("Starting echo client..."); string ipaddress = "127.0.0.1"; TcpClient client = null; NetworkStream netstream = null; try { client = new TcpClient(ipaddress,1000); netstream = client.GetStream(); } catch { Console.ReadKey(); Environment.Exit(0); } while(true) { Console.WriteLine("Message : "); string t = Console.ReadLine(); string readdata = null; Console.WriteLine("n"); if (write(t,netstream)) { Console.WriteLine("Message sent."); if (client.Available!=0) { readdata = read(netstream); Console.WriteLine("MESSAGE FROM SERVER : "+readdata); } } else { Console.WriteLine("Unable to send message."); } } } static bool write(string dat, NetworkStream stream) { try { StreamWriter writer = new StreamWriter(stream) { AutoFlush = true }; try{writer.WriteLine(dat);} catch (IOException){return false;} if (SHAHash(dat, "DATA") != SHAHash(read(stream), "DATA")) return false; }catch (InvalidOperationException){return false;} return true; } static string read(NetworkStream stream) { StreamReader reader = new StreamReader(stream); string readdata = null; try { readdata = reader.ReadLine(); reader.BaseStream.Flush(); } catch(IOException) { return null; } return readdata; } }
函数 SHAHash 在这篇文章中没有显示。它的格式是SHAHash(message,salt)。
面临的问题是服务器发送的消息并不总是由客户端读取。有时服务器发送的数据会显示客户端控制台,有时则不会。
我应该对上面的代码进行什么更正,以便我只能在服务器发送数据时从服务器读取数据。也就是说,我要求仅在服务器向客户端发送一些数据时才执行以下代码,否则不应执行。
readdata = read(netstream);
Console.WriteLine("MESSAGE FROM SERVER : "+readdata);
使用刷新或自动刷新时要谨慎。有时它会在发送/接收操作之前执行...但这通常在使用线程时发生。
我的第一个提示是流读取器/写入器没有正确销毁。尝试将它们打包到 using 语句中。
TCP 不是同步的,因此您无法写入数据并期望响应立即可用。执行以下检查时
if (client.Available!=0)
不能保证服务器已发送任何响应。您需要继续检查,直到有可用数据或异步读取数据
我会使用 NetworkStream.BeginRead 和回调来获取服务器响应
class StreamData
{
public NetworkStream netstream;
public byte[] myReadBuffer;
}
class TcpEchoClient
{
static void Main(string[] args)
{
Console.WriteLine("Starting echo client...");
string ipaddress = "127.0.0.1";
TcpClient client = null;
NetworkStream netstream = null;
try
{
client = new TcpClient(ipaddress, 13000);
netstream = client.GetStream();
}
catch
{
Console.ReadKey();
Environment.Exit(0);
}
var streamData = new StreamData
{
netstream = netstream,
myReadBuffer = new byte[1024],
};
netstream.BeginRead(streamData.myReadBuffer, 0, streamData.myReadBuffer.Length,
new AsyncCallback(myReadCallBack),
streamData);
while (true)
{
Console.WriteLine("Message : ");
string t = Console.ReadLine();
Console.WriteLine("n");
if (write(t, netstream))
{
Console.WriteLine("Message sent.");
}
else
{
Console.WriteLine("Unable to send message.");
}
}
}
static void myReadCallBack(IAsyncResult ar)
{
var streamData = (StreamData)ar.AsyncState;
int bytesRead = streamData.netstream.EndRead(ar);
var readdata = Encoding.ASCII.GetString(streamData.myReadBuffer, 0, bytesRead);
//Be aware that this might not be the complete message depending on the size of the message and the buffer size
Console.WriteLine("You received the following message : " + readdata);
//Start waiting for more data
streamData.netstream.BeginRead(streamData.myReadBuffer, 0, streamData.myReadBuffer.Length,
new AsyncCallback(myReadCallBack),
streamData);
}
static bool write(string dat, NetworkStream stream)
{
try
{
StreamWriter writer = new StreamWriter(stream) { AutoFlush = true };
try { writer.WriteLine(dat); }
catch (IOException) { return false; }
//if (SHAHash(dat, "DATA") != SHAHash(read(stream), "DATA"))
// return false;
}
catch (InvalidOperationException) { return false; }
return true;
}
}