写入服务器的不同数据正在附加成为一个字符串
Different data written to the server are becoming appended to become a single string
N.B。参考.
我写这个class是为了在服务器端用作代理,在客户端用作客户端。
我当前的源代码如下:
public class ClientClass : IDisposable
{
private string Host { get; set; }
private int Port { get; set; }
public bool IsConnected { private set; get; }
public TcpClient Tcp { get; private set; }
private System.Net.Sockets.NetworkStream stream;
public ClientClass()
{
IsConnected = false;
}
//constructor for server program.
public ClientClass(TcpListener listener)
{
Tcp = listener.AcceptTcpClient();
Host = ((IPEndPoint)Tcp.Client.RemoteEndPoint).Address.ToString();
Port = ((IPEndPoint)Tcp.Client.LocalEndPoint).Port;
IsConnected = true;
stream = Tcp.GetStream();
}
//constructor for client.
public ClientClass(string host, int port)
{
Host = host;
Port = port;
}
public string Read()
{
if (IsConnected)
{
byte[] buffer = new byte[Tcp.ReceiveBufferSize];//create a byte array
int bytesRead = stream.Read(buffer, 0, Tcp.ReceiveBufferSize);//read count
string str = Encoding.ASCII.GetString(buffer, 0, bytesRead);//convert to string
return str.TrimEnd(new char[] {'\r', '\n'});//remove CR and LF
}
else
{
throw new Exception("Client " + ID + " is not connected!");
}
}
public void Write(string str)
{
if (IsConnected)
{
str = str + Constants.CRLF;// add CR and LF
byte[] bytesToSend = ASCIIEncoding.ASCII.GetBytes(str);
stream.Write(bytesToSend, 0, bytesToSend.Length);
stream.Flush();
}
else
{
throw new Exception("Client " + ID + " is not connected!");
}
}
public bool Connect()
{
if (IsConnected == false)
{
IsConnected = true;
Tcp = new TcpClient(Host, Port);
stream = Tcp.GetStream();
return true;
}
return false;
}
public bool Disconnect()
{
if (IsConnected)
{
if (Tcp != null)
{
//stream.Flush();
stream.Close();
//Tcp.GetStream().Flush();
//Tcp.GetStream().Close();
Tcp.Close();
return true;
}
}
return false;
}
#region dispose pattern
// Flag: Has Dispose already been called?
bool disposed = false;
// Public implementation of Dispose pattern callable by consumers.
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
// Protected implementation of Dispose pattern.
protected virtual void Dispose(bool disposing)
{
if (disposed)
return;
if (disposing)
{
// Free any other managed objects here
if (stream != null)
{
stream.Flush();
stream.Close();
stream.Dispose();
stream = null;
}
if (Tcp != null)
{
if (Tcp.Connected)
{
Tcp.Client.Disconnect(false);
Tcp.Client.Close();
Tcp.Client.Dispose();
Tcp.Client = null;
//Tcp.GetStream().Flush();
//Tcp.GetStream().Close();
Tcp.Close();
Tcp = null;
}
}
}
// Free any unmanaged objects here.
// ...
disposed = true;
}
~ClientClass()
{
Dispose(false);
}
#endregion
}
我遇到的问题是:
ClientClass client = new ClientClass(...);
client.Write("1");
client.Write("2");
client.Write("hello");
将作为唯一输入到达另一端:
"12hello"
,而不是三个单独的输入 {"1"、"2" 和 "hello"}。
我该如何解决这个问题?
TCP 是流协议,不是数据包协议。您所保证的只是相同顺序的相同字节(或套接字故障), 而不是 组的组成。所以:除此之外的任何内容 你都需要自己添加 。对于基于文本的协议,一种常见的方法可能是在每个逻辑负载之后放置一个换行符 (\n
),然后在解码时查找相同的内容。对于二进制协议,长度前缀更为常见。
N.B。参考
我写这个class是为了在服务器端用作代理,在客户端用作客户端。
我当前的源代码如下:
public class ClientClass : IDisposable
{
private string Host { get; set; }
private int Port { get; set; }
public bool IsConnected { private set; get; }
public TcpClient Tcp { get; private set; }
private System.Net.Sockets.NetworkStream stream;
public ClientClass()
{
IsConnected = false;
}
//constructor for server program.
public ClientClass(TcpListener listener)
{
Tcp = listener.AcceptTcpClient();
Host = ((IPEndPoint)Tcp.Client.RemoteEndPoint).Address.ToString();
Port = ((IPEndPoint)Tcp.Client.LocalEndPoint).Port;
IsConnected = true;
stream = Tcp.GetStream();
}
//constructor for client.
public ClientClass(string host, int port)
{
Host = host;
Port = port;
}
public string Read()
{
if (IsConnected)
{
byte[] buffer = new byte[Tcp.ReceiveBufferSize];//create a byte array
int bytesRead = stream.Read(buffer, 0, Tcp.ReceiveBufferSize);//read count
string str = Encoding.ASCII.GetString(buffer, 0, bytesRead);//convert to string
return str.TrimEnd(new char[] {'\r', '\n'});//remove CR and LF
}
else
{
throw new Exception("Client " + ID + " is not connected!");
}
}
public void Write(string str)
{
if (IsConnected)
{
str = str + Constants.CRLF;// add CR and LF
byte[] bytesToSend = ASCIIEncoding.ASCII.GetBytes(str);
stream.Write(bytesToSend, 0, bytesToSend.Length);
stream.Flush();
}
else
{
throw new Exception("Client " + ID + " is not connected!");
}
}
public bool Connect()
{
if (IsConnected == false)
{
IsConnected = true;
Tcp = new TcpClient(Host, Port);
stream = Tcp.GetStream();
return true;
}
return false;
}
public bool Disconnect()
{
if (IsConnected)
{
if (Tcp != null)
{
//stream.Flush();
stream.Close();
//Tcp.GetStream().Flush();
//Tcp.GetStream().Close();
Tcp.Close();
return true;
}
}
return false;
}
#region dispose pattern
// Flag: Has Dispose already been called?
bool disposed = false;
// Public implementation of Dispose pattern callable by consumers.
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
// Protected implementation of Dispose pattern.
protected virtual void Dispose(bool disposing)
{
if (disposed)
return;
if (disposing)
{
// Free any other managed objects here
if (stream != null)
{
stream.Flush();
stream.Close();
stream.Dispose();
stream = null;
}
if (Tcp != null)
{
if (Tcp.Connected)
{
Tcp.Client.Disconnect(false);
Tcp.Client.Close();
Tcp.Client.Dispose();
Tcp.Client = null;
//Tcp.GetStream().Flush();
//Tcp.GetStream().Close();
Tcp.Close();
Tcp = null;
}
}
}
// Free any unmanaged objects here.
// ...
disposed = true;
}
~ClientClass()
{
Dispose(false);
}
#endregion
}
我遇到的问题是:
ClientClass client = new ClientClass(...);
client.Write("1");
client.Write("2");
client.Write("hello");
将作为唯一输入到达另一端:
"12hello"
,而不是三个单独的输入 {"1"、"2" 和 "hello"}。
我该如何解决这个问题?
TCP 是流协议,不是数据包协议。您所保证的只是相同顺序的相同字节(或套接字故障), 而不是 组的组成。所以:除此之外的任何内容 你都需要自己添加 。对于基于文本的协议,一种常见的方法可能是在每个逻辑负载之后放置一个换行符 (\n
),然后在解码时查找相同的内容。对于二进制协议,长度前缀更为常见。