- android - RelativeLayout 背景可绘制重叠内容
- android - 如何链接 cpufeatures lib 以获取 native android 库?
- java - OnItemClickListener 不起作用,但 OnLongItemClickListener 在自定义 ListView 中起作用
- java - Android 文件转字符串
我正在编写一个客户端应用程序(Windows 服务),它定期从服务器读取数据并将数据写入服务器。如果他收到的帧被理解,服务器被配置为总是回复客户端。我有以下发送和接收方法:
public byte[] Sendmessage(byte[] arrbMessage)
{
byte[] arrbDataInput; // byteArray for received data
try
{
_oStream = _oClient.GetStream(); // try to get a networkstream
}
catch (InvalidOperationException e)
{
Connect(); // if this fails, tcpclient is probably disconnected, reconnect client and networstream
}
if (_oClient.Connected)
try
{ // Send the arrbMessage to the connected TcpServer.
string sKey = "123456789ABC";
byte[] arrbMessageEncrypted = EncryptedFrame(arrbMessage, sKey);
if (_oStream.CanWrite) // if stream is available for writing
{
_oStream.Write(arrbMessageEncrypted, 0, arrbMessageEncrypted.Length); //send message
_oStream.Flush(); //Clear stream
}
// Receive the TcpServer.response.
if (_oStream.CanRead) // if stream is available for reading
{
arrbDataInput = new byte[256]; // set inputbuffer to 256
//_oClient.NoDelay = true; // don't wait if nothing is received
// Read the first batch of the TcpServer response bytes.
_oStream.ReadTimeout = 2000;
Int32 bytes = _oStream.Read(arrbDataInput, 0, arrbDataInput.Length); //read out data, put datalength in "bytes"
Array.Resize(ref arrbDataInput, bytes); // resize array to length of received data
_oStream.Close(); // close the network stream
if (arrbDataInput.Length > 0)
{
byte[] arrbMessageDecrypted = DecryptedFrame(arrbDataInput, sKey);
if (CheckBusy(arrbMessageDecrypted))
throw new ArgumentNullException();
return arrbMessageDecrypted;
}
return null; // return the received data
}
}
catch (ArgumentNullException e)
{
return Sendmessage(arrbMessage);
}
catch (SocketException e)
{
}
catch (System.IO.IOException e)
{
while (!_oClient.Connected)
{
Connect();
}
}
else
{
while (!_oClient.Connected)
{
Connect();
}
}
return null;
}
我很难让流保持打开状态,所以目前我们每次发送和接收数据后都会关闭它。我应该让流和 tcpclient 打开吗?该函数被定期调用。
最佳答案
我开发过一个应用程序,其中 NetworkStream
在应用程序启动时打开,仅在以下情况下关闭:
tcpClient.Connected
属性将返回 false,我们关闭 NetworkStream
和 TcpClient
。然后我们启动一个每秒计时器,它将检查服务器的可用性,一旦找到服务器,它就会重新连接,从而打开 TcpClient
和 NetworkStream
NetworkStream
和 TcpClient
并启动轮询线程以检查服务器的可用性。我们没有观察到保持 NetworkStream 和 TcpClient 打开的任何问题。 可能是代码的其他部分导致了问题。
断章取义,但建议:当您从NetworkStream
读取时,您只读取了256 个字节;如果数据超过 256 字节怎么办?
我会为每组数据建议一些分隔符;例如如果您的加密系统生成 Base64 哈希,您可以安全地使用 ';' (分号)作为数据分隔符。 (我们使用\n 作为命令分隔符)但这完全取决于您的场景。
另外,使用如下类型的逻辑来读取和存储接收到的字符串,只有在分隔符可用时才解密和执行。这将确保您永远不会收到部分字符串并尝试对其进行解密。
string allPendingCommands = "";
string commandSeparator = ";"; // your command separator character here
while(tcpClient.Connected)
{
if (!networkStream.DataAvailable)
System.Threading.Thread.Sleep(100);
// you can change it depending on the frequency of availability of data
// read 256 bytes into you array
// convert the byte[] to string
// add the newly read text to the text remaining from previous command execution.
allPendingCommands += theReadBytes;
while(allPendingCommands.Contains(commandSeparator))
{
// it may happen that the string at the moment contains incomplete
// string, which can also not be decoded/decrypted. This loop will
// stop and the next 256 bytes (as much available) will be read and
// appended into allPendingCommands. When the command gets completed,
// allPendingCommands will contain the separator character and the
// command will be properly decoded and executed.
int idx = allPendingCommands.IndexOf(commandSeparator);
string command = allPendingCommands.SubString(0, idx);
allPendingCommand = allPendingCommand.SubString(idx + 1);
// convert those bytes back to string (after decrypting/decoding)
command = Decrypt(command);
// Process the Command (command); // do the needful in the function
}
}
关于c# - 何时关闭 tcpclient 和 networkstream,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23381627/
要关闭 TcpClient,必须关闭流。通常的做法是: client.GetStream().Close(); client.Close(); 因此仅使用 client
我正在阅读 the documentation on TcpClient.Close()并注意到这一点: Calling this method will eventually result in t
用于同步消息交换的我的客户端类: public class AsClient { private TcpClient connection; public AsClient(int s
我正在制作一个向许多 TCP 监听器发送数据的程序。如果不再使用其中一个 TCP 发送 channel ,我们是否需要使用 TCPClient.close 将其关闭。如果我们让它打开会怎样? 谢谢!
.NET 允许两种非常相似的方式从网络“读取”(假设 TCP 连接): 1. TcpClient.GetStream().Read() 2. TcpClient.Client.Receive() 通过
我找到了一些关于如何用 C# 编写 TCP/IP 客户端-服务器应用程序的代码服务器 Main 以此开头: TcpListener serverSocket = new TcpListener(888
我正在尝试连接到本地网络内的路由器。到目前为止,我已经使用了 TcpClient。 检查我的代码: public static void RouterConnect() {
服务器 : public class TcpServer { private TcpListener tcpListener; private static ManualResetEv
我想使用 TcpClient 发送 HTTP 请求。考虑以下代码: byte[] buf = new byte[1024]; string header = "GET
我在半关闭 TcpClient 时遇到了严重问题。我想做的是: 在客户端: 发送消息 关闭用于发送的底层套接字 收到回复 关闭用于读取的底层套接字(或者,此时,直接关闭它) 在服务器上: 接收消息 关
我有一个客户端和服务器,都有接收和发送方法,并且都使用相同的数据包类、数据包头大小和反序列化等。 如果我只发送较小的文本消息包,一切正常,但是当我尝试发送图像时,缓冲区溢出并且出现内存不足异常。奇怪的
在我的 C# 应用程序中,我有一个线程,它基本上不断地从 TcpClient 读取数据,直到被告知停止。为此,我使用 WaitHandles,例如: private ManualResetEvent
我有一个客户端-服务器程序。 我正在发送这样的数据: private void Sender(string s,TcpClient sock) { try { byte[] b
这个问题在这里已经有了答案: C# network connection running from shared drive (1 个回答) 关闭 7 年前。 我几天前问过类似的问题。那时,我正在尝
我有一个 TCPClient,它创建一个流,当 DataAvailable 时我从中读取流。 每 20 秒 !DataAvailable 我会使用 ACK 消息对套接字执行 ping 操作,以防止流关
我正在使用 SwifSockets:https://github.com/swiftsocket/SwiftSocket :按照有关如何使用它的说明后,我在堆栈溢出上找到了此代码:Sending Me
我在继承的一些代码中有一个奇怪的行为 - 下面的简化示例演示了如果内置到普通控制台应用程序中的问题。 WhoIs 在第 5 次调用时达到其使用限额 - 并返回一条消息 + 关闭套接字。使用 ReadL
我正在用 C# 开发一个 Tcp 客户端,我正在使用 TcpClient 类。我无法连接到服务器。 调试应用程序我可以看到对 Connect 的调用是成功的,但是在我这样做之后,我用 netstat
我有一个我似乎无法弄清楚的问题,请帮忙。我创建了一个类来处理使用 TcpClient 的某些硬件的接口(interface)。我希望此类在 HW 被销毁之前向 HW 发送最后一个命令。 为了解决这个问
您好,感谢您的帮助。这次想问一下TcpClient。我有一个服务器程序,我正在编写一个客户端程序。此客户端使用 TcpClient。首先是创建一个新客户端 clientSocket=new TcpCl
我是一名优秀的程序员,十分优秀!