好吧,我完全理解TCP是基于流的,而不是基于消息的——我不在乎这个。
我所要做的是尝试简单地序列化一些内容并通过网络将其发送到另一个使用相同的基于消息的协议的应用程序。
问题是,每当我序列化数据(我序列化为XML),然后将其写入网络流时,最糟糕的事情永远不会写入数据。直到我关闭程序并关闭流之后,流才真正发送数据。究竟发生了什么-TCP是否在等待足够的数据发送?它在等我的东西吗?(我怀疑前者,因为我能写简单的行,而且写得很好。)
这是我客户的代码:
TcpClient client = new TcpClient();
client.Connect(IPAddress.Parse("127.0.0.1"), 10100);
NetworkStream ns = client.GetStream();
StreamWriter writer = new StreamWriter(ns);
ListenerThread th = new ListenerThread(new StreamReader(ns));
new Thread(th.run).Start();
XmlSerializer serializer = new XmlSerializer(typeof(Message), new Type[] {typeof(AuthenticationMessage), typeof(ChangeChatRoomMessage), typeof(ChangePasswordMessage), typeof(ConnectionStatusMessage), typeof(InitializeMessage), typeof(StatusMessage), typeof(SuccessMessage), typeof(TextMessage)});
string file = "<some test xml file>";
while(true)
{
FileStream stream = new FileStream(file, FileMode.Open, FileAccess.Read);
StreamReader reader = new StreamReader(stream);
Message newmsg = (Message)serializer.Deserialize(reader);
stream.Close();
serializer.Serialize(writer, newmsg);
writer.Flush();
file = Console.ReadLine();
}
这是服务器的代码:
public void HandleMessage()
{
Message msg = (Message)serializer.Deserialize(reader);
Console.WriteLine("Read Message " + msg.GetType());
}
public void Start()
{
while(true)
{
Socket socket = listener.AcceptSocket();
NetworkStream stream = new NetworkStream(socket);
reader = new StreamReader(stream);
HandleMessage();
stream.Close();
}
}
我的程序已经运行了20分钟,没有任何内容发送到服务器。我尽我所能,刷新我的编写器缓冲区(显然是文本编写器,而不是网络流),并将客户机设置为nodelay等…发生了什么?为什么?
最佳答案
好吧,所以我理解TCP是基于流的
不是基于信息的-我不在乎。
实际上这很重要,你应该关心它。向服务器发送数据时,您不仅应尝试发送某些消息,还应定义一些协议(或使用现有的协议之一),其中客户端向服务器指示要发送的数据量等。
这里有一个例子说明你如何继续。在本例中,客户机将总消息的长度作为前4个字节发送。
服务器:
class Program
{
static void Main()
{
var listener = new TcpListener(new IPEndPoint(IPAddress.Loopback, 10100));
listener.Start();
while (true)
{
using (var client = listener.AcceptTcpClient())
using (var stream = client.GetStream())
using (var reader = new BinaryReader(stream))
{
// The first 4 bytes of the message will indicate
// the total message length
var length = reader.ReadInt32();
var buffer = reader.ReadBytes(length);
Console.WriteLine("Received {0} bytes from client:", length);
Console.WriteLine("{0}", Encoding.UTF8.GetString(buffer));
}
}
}
}
客户:
class Program
{
static void Main()
{
using (var client = new TcpClient("127.0.0.1", 10100))
using (var stream = client.GetStream())
using (var writer = new BinaryWriter(stream))
{
var message = "<some test xml file>";
var buffer = Encoding.UTF8.GetBytes(message);
// Send the total message length in the first 4 bytes
// so that the server knows how much it has to read
writer.Write(buffer.Length);
writer.Write(buffer);
Console.WriteLine("Successfully sent {0} bytes to server", buffer.Length);
}
}
}