我有一个TcpClient对象,它使用其底层NetworkStream.Write()将一些数据发送到服务器.因此,我有:
TcpClient server = new TcpClient(serverName, 50001);
/* ... */
NetworkStream stream = server.GetStream();
Run Code Online (Sandbox Code Playgroud)
现在,按下按钮时,连接应该关闭.什么是关闭连接的正确方法?MSDN文档说关闭TcpClient(使用.Close())实际上并不关闭套接字,只关闭TcpClient资源(这至少是我理解文档的方式).
那么,下一个代码会正确关闭连接吗?
stream.Close();
server.Close();
Run Code Online (Sandbox Code Playgroud)
这是否足够,或者我应该首先检查(以某种方式)是否可以关闭流(或服务器)(如果连接是半开的或某些东西)......
更重要的是,NetworkStream.Close()MSDN文档声明它释放资源(甚至是套接字),因此关闭流可能就足够了,因为我在此之后阻止使用TcpClient.
什么是正确的方法?
我需要读取NetworkStream哪个会随机发送数据,数据包的大小也会不断变化.我正在实现一个多线程应用程序,其中每个线程都有自己的流来读取.如果流上没有数据,应用程序应该一直等待数据到达.但是,如果服务器完成了发送数据并终止了会话,那么它应该退出.
最初我使用该Read方法从流中获取数据,但它用于阻塞线程并一直等待直到数据出现在流上.
MSDN上的文档建议,
如果没有可用于读取的数据,则Read方法返回0.如果远程主机关闭连接,并且已收到所有可用数据,则Read方法立即完成并返回零字节.
但在我的情况下,我从来没有得到Read返回0并优雅退出的方法.它只是无限期地等待.
在我的进一步调查中,我遇到了BeginRead监视流并在接收数据时异步调用回调方法.我也试图使用这种方法寻找各种实现,但是,我无法确定何时使用BeginRead是有益的而不是Read.
在我看来,它BeginRead具有异步调用的优势,它不会阻止当前线程.但是在我的应用程序中,我已经有了一个单独的线程来读取和处理来自流的数据,所以这对我来说没什么大不了的.
任何人都可以帮我理解等待和退出机制,
BeginRead它有什么不同Read?
实现所需功能的最佳方法是什么?
我的目标是通过LAN网络传输*.wav文件,没有延迟或只有最小的.
我们还按部件读取服务器机器上的文件,两者都是320字节.在此之后,我们通过UDP发送数据包并在抖动缓冲区中写入接收.抖动缓冲区的大小为10.我应该在定时器上设置什么延迟以获得清晰的声音?
这是发件人:
void MainWindow::on_start_tx_triggered()
{
timer1 = new QTimer (this);
udpSocketout = new QUdpSocket(this);
qDebug()<<"Start";
for (int i = 0; i < playlist.size(); ++i)
{
inputFile.setFileName(playlist.at(i));
qDebug()<<inputFile.fileName();
if (!inputFile.open(QIODevice::ReadOnly))
{
qDebug()<< "file not found;";
}
}
connect(timer1, SIGNAL(timeout()), this, SLOT(writeDatagrams()));
timer1->start(5);
}
void MainWindow::writeDatagrams()
{
if(!inputFile.atEnd()){
payloadout = inputFile.read(320);
}
qDebug()<<payloadout;
QDataStream out(&datagramout, QIODevice::WriteOnly);
out.setVersion(QDataStream::Qt_4_7);
out << qint64(0);
out << payloadout;
out.device()->seek(qint64(0));
out << qint64(datagramout.size() - sizeof(qint64));
qint64 writtenBytes = udpSocketout->writeDatagram(datagramout, remoteHOST, remotePORT);
qDebug() << "Sent " << writtenBytes …Run Code Online (Sandbox Code Playgroud) 我寻找满足以下要求的最佳实践:
我想知道我使用的框架BeginReceive和EndReceive实现的IAsyncResult回调是否是最先进的,因为我的目标是.Net 4.5.有没有更好的解决方案,例如使用NetworkStream或其他API选择?使用BeginReceive/EndReceive实现真正让我感到困惑的是,在EndReceive之后,我必须再次调用BeginReceive并再次注册回调.这对我来说听起来像是一个可怕的开销.为什么不能将新数据异步在任何时候,在同一时间增加了另一个环境中建立被然后通过引发的事件路由的完整信息?
使用IAsyncResult的论点通常是在处理线程处理时给出的,但是反对以下内容:使用NetworkStream并简单地读取和写入流.如上所述,只交换字符串消息,每个协议的每条消息都由换行符标记完成.单独的任务/线程将轮询流式读取器(基于网络流)ReadLine().它可能不会比那更简单,可以吗?
我基本上要问的是,以下代码如何才能真正实现异步?
public class SocketClient
{
private TcpClient client;
private StreamReader reader;
private StreamWriter writer;
public event Action<string> MessageCallback;
public SocketClient(string hostname, int port)
{
client = new TcpClient(hostname, port);
try
{
Stream stream = client.GetStream();
reader = new StreamReader(stream);
writer = new StreamWriter(stream);
writer.AutoFlush = true;
//Start Listener on port
StartListener();
}
catch (Exception e)
{
throw new Exception(e.ToString());
}
}
public void …Run Code Online (Sandbox Code Playgroud) 我有一个字节数组,我正在从NetworkStream中读取.前两个字节表示后面的数据包的长度,然后将数据包读入该长度的字节数组.我需要从NetworkStream/byte数组中读取的数据有几个字符串,即由新行字符终止的可变长度数据,以及一些固定宽度字段,如字节和长整数.所以,像这样:
// I would have delimited these for clarity but I didn't want
// to imply that the stream was delimited because it's not.
StringbyteStringStringbytebytebytelonglongbytelonglong
Run Code Online (Sandbox Code Playgroud)
我知道(并且有一些说法)正在发生的数据包的格式,我需要做的是读取每个字符串值的"行",但读取字节和长度的固定字节数.到目前为止,我提出的解决方案是使用while循环将字节读入临时字节数组,直到有换行符.然后,将字节转换为字符串.这对我来说似乎很尴尬,但我没有看到另一种显而易见的方式.我意识到我可以使用,StreamReader.ReadLine()但这将涉及另一个流,我已经有了NetworkStream.但如果这是更好的解决方案,我会试一试.
我考虑的另一个选项是让我的后端团队为那些String值的长度写一个或两个字节,这样我就可以读取长度,然后根据指定的长度读取字符串.
所以,正如你所看到的,我有一些选择如何解决这个问题,我希望你的意见是关于你认为最好的方法.这是我现在用于以字符串形式读取整个数据包的代码.下一步是打破数据包的各个字段,并根据数据包中的数据完成需要完成的实际编程工作,创建对象,更新UI等.
string line = null;
while (stream.DataAvailable)
{
//Get the packet length;
UInt16 packetLength = 0;
header = new byte[2];
stream.Read(header, 0, 2);
// Need to reverse the header array for BitConverter class if architecture is little endian.
if (BitConverter.IsLittleEndian)
Array.Reverse(header);
packetLength = BitConverter.ToUInt16(header,0);
buffer = new …Run Code Online (Sandbox Code Playgroud) 我的应用程序中有一个工作线程,负责三个不同的事情.在我编写的队列中,有两个作业的请求出现,另一个作业在网络流上出现请求时被激活.我希望我的工作线程在没有工作要做的时候等待.这两个队列很容易,因为它们暴露了一个在有项目时设置的ManualResetEvent,但是NetworkStream似乎没有这个.已从TcpClient检索NetworkStream.
我所追求的是看起来像这样的代码:
while (notDone)
{
WaitHandle.WaitAny(new WaitHandle[] { queue1.HasData, queue2.HasData, netStream.HasData } );
// ...
if (netStream.DataAvailable)
{
netStream.Read(buffer, 0, 20);
// process buffer
}
}
Run Code Online (Sandbox Code Playgroud)
有没有人知道获取在NetworkStream有数据时设置的WaitHandle的方法?
我正在建立一种在服务器和客户端之间进行通信的方法.我现在如何工作,是一个流的第一个字节将包含一个指示器,指示即将发生的事情,然后查找该请求的类我可以确定请求的长度:
stream.Read(message, 0, 1)
if(message == <byte representation of a known class>)
{
stream.Read(message, 0, Class.RequestSize);
}
Run Code Online (Sandbox Code Playgroud)
我很好奇如何处理类大小未知的情况,如果在读取已知请求后数据已损坏.
我想我可以在流中插入某种分隔符,但由于一个字节只能在0-255之间,我不知道如何创建一个唯一的分隔符.我是否要将模式放入流中以表示消息的结束?我怎样才能确定这种模式是否足够独特,不会被误认为是实际数据?
在以下场景中;
System.Net.Sockets.TcpClient TC = SomeHowObtained;
System.Net.Sockets.NetworkStream NS = TC.GetStream();
Run Code Online (Sandbox Code Playgroud)
使用NS.DataAvailable和检查有什么区别TC.Available > 0吗?
我有一个应用程序,通过套接字连接发送不同大小的可序列化对象,我希望它尽可能地扩展.也可能有数十甚至数百个连接.
所以似乎有太多的方法可以给这只猫留下光彩,而且我不确定什么才是最有效的.我是:
只需使用BinaryFormatter读取NetworkStream?
var netStream = client.GetStream();
var formatter = new BinaryFormatter();
var obj = formatter.Deserialize(netStream);
Run Code Online (Sandbox Code Playgroud)
或者使用新的异步/等待内容做一些魔术:
using(var ms = new MemoryStream())
{
var netStream = client.GetStream();
var buffer = new byte[1028];
int bytesRead;
while((bytesRead = await netStream.ReadAsync(buffer, 0, buffer.length)) > 0) {
ms.Write(buffer, 0, buffer.Length);
}
var formatter = new BinaryFormatter();
var obj = formatter.Deserialize(ms);
}
Run Code Online (Sandbox Code Playgroud)
或者与上面类似,只利用新的CopyToAsync方法:
using(var ms = new MemoryStream())
{
var netStream = client.GetStream();
await netStream.CopyToAsync(ms); //4096 default buffer.
var …Run Code Online (Sandbox Code Playgroud) 我还没有"得到"异步并等待,我正在寻找一些关于我即将解决的特定问题的澄清.基本上,我需要编写一些能够处理TCP连接的代码.它基本上只是接收数据并处理它,直到连接关闭.
我通常使用NetworkStream BeginRead和EndRead模式编写此代码,但由于async/await模式更清晰,我很想使用它.但是,由于我无法完全理解这些涉及到什么,我对后果有点警惕.一个人会比另一个人使用更多的资源; 将使用一个线程,其他人将使用IOCP等.
令人费解的例子时间.这两个做同样的事情 - 计算流中的字节数:
class StreamCount
{
private Stream str;
private int total = 0;
private byte[] buffer = new byte[1000];
public Task<int> CountBytes(Stream str)
{
this.str = str;
var tcs = new TaskCompletionSource<int>();
Action onComplete = () => tcs.SetResult(total);
str.BeginRead(this.buffer, 0, 1000, this.BeginReadCallback, onComplete);
return tcs.Task;
}
private void BeginReadCallback(IAsyncResult ar)
{
var bytesRead = str.EndRead(ar);
if (bytesRead == 0)
{
((Action)ar.AsyncState)();
}
else
{
total += bytesRead;
str.BeginRead(this.buffer, 0, 1000, this.BeginReadCallback, ar.AsyncState);
}
}
} …Run Code Online (Sandbox Code Playgroud) networkstream ×10
c# ×9
.net ×3
async-await ×2
asynchronous ×2
tcp ×2
.net-4.5 ×1
audio ×1
bytearray ×1
c#-5.0 ×1
qt ×1
sockets ×1
streaming ×1
tcpclient ×1