了解 TCP 服务器是否已发送数据


  1. 我有一个TCP服务器,它只为客户端发送到服务器的某些消息将数据写回客户端。
  2. 它基本上是一个基于命令的服务器,服务器只对某些命令使用字符串进行响应,否则不会将任何内容发送回客户端。

  3. 下面给出的代码是一种方法,它假设如果服务器发送任何数据,它将其显示为"来自服务器的消息",并附加了发送的数据。

    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;
}

}

最新更新