好的,所以我有点困惑,为什么我无法在任何地方找到它,或者如果它不存在那么为什么微软没有实现呢?
所以这是我的场景,我有一个NetworkStream,它有一个名为DataAvailable的可爱的小布尔,我需要的是一个事件,跳出来说"嘿,有数据可供你使用!" (因为我很懒,而且我宁愿被告知有数据可用,而不是继续问"好吧,有没有可用的数据?"一遍又一遍,直到我收到回复"实际上,这次有").
类似于SerialPort(它有一个很好的事件(DataReceived),它通知我从端口接收数据)会很不错.但我正在使用带有NetworkStream的Socket.
如果有一些显而易见的东西我错过了,请指出正确的方向,但如果没有,这是否意味着我将不得不在DataAvailable属性上使用一些数据绑定,当它设置为true时,调用我的拥有'自制'活动/功能?如果这样的话,请你给我一个小例子让球滚动?
编辑
我的完美答案是有人来和我解释如何找到/创建与SerialPort一起使用的DataReceived事件非常相似的东西,但是为通过NetworkStream流式传输的Socket实现了!
再次感谢,谢谢.
它一直出现错误"在非连接套接字上不允许操作"
var ServerStream = Connect2Server.GetStream();
Run Code Online (Sandbox Code Playgroud)
而且我不确定为什么
下面是该函数的其余代码
var buffersize = 0;
var Convert2Tet = new ASCIIEncoding();
var Connect2Server = new TcpClient();
var ServerEndPoint = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 8801);
var ServerStream = Connect2Server.GetStream();
Console.WriteLine("Connecting to Server");
Connect2Server.Connect(ServerEndPoint);
var WelcomeMessage = new byte[4096];
ServerStream.Read(WelcomeMessage, 0, 4096);
Console.Write(Convert2Tet.GetChars(WelcomeMessage));
var UserCredentials = Console.ReadLine();
buffersize = Convert2Tet.GetByteCount(UserCredentials);
var Credentials = new byte[buffersize];
Credentials = Convert2Tet.GetBytes(UserCredentials);
ServerStream.Write(Credentials, 0, buffersize);
Run Code Online (Sandbox Code Playgroud) 我目前正在测试我编写的托管c#网络库,我遇到了偶然的问题.这个问题在networkstream.write()上显示为非常一致(总是在30ms内)5000ms块,可能占所有发送操作的1%.这是在测试环境中,全部在本地运行,每次使用完全相同的数据包大小(2MB).在客户端,我不断将以下内容写入连接的网络流:
tcpClientNetworkStream.Write(headerBytes, 0, headerBytes.Length);
tcpClientNetworkStream.Write(dataBytes, 0, dataBytes.Length);
Run Code Online (Sandbox Code Playgroud)
在服务器端,我使用异步读取等待数据.一旦数据出现,我在tcpClientNetworkStream.DataAvailable上使用while循环,直到收到所有数据.
我知道如果缓冲区已满,networkstream.write()可能会阻塞,但如果这是问题我想不出更快的方法在服务器端清除它们(发送和接收缓冲区大小默认为8192字节) .块如此一致的事实似乎很奇怪.我的第一个想法可能是某种形式的Thread.Sleep但是进行完整的项目搜索没有显示.如果有人能帮助阐明这个问题,那将非常感激.
渣
编辑添加:一个似乎让问题消失的黑客攻击如下(尽管由于BlockCopy而导致相关的性能下降):
byte[] bytesToSend = new byte[headerBytes.Length + dataBytes.Length];
Buffer.BlockCopy(headerBytes, 0, bytesToSend, 0, headerBytes.Length);
Buffer.BlockCopy(dataBytes, 0, bytesToSend, headerBytes.Length, dataBytes.Length);
tcpClientNetworkStream.Write(bytesToSend, 0, bytesToSend.Length);
Run Code Online (Sandbox Code Playgroud)
编辑add2:我也通过使用两个异步写入和两者之间的线程信号来重现问题.目前我唯一的解决方案就是上面编辑中的单一写操作.
编辑add3:好的,另一个可能的修复如下.我仍然有兴趣知道为什么连续写它会像它一样"阻塞".
BufferedStream sendStream = new BufferedStream(tcpClientNetworkStream);
sendStream.Write(bytesToSend, 0, bytesToSend.Length);
sendStream.Write(packet.PacketData, 0, packet.PacketData.Length);
sendStream.Flush();
Run Code Online (Sandbox Code Playgroud)
编辑add4:经过进一步的广泛测试后,'edit to add3'中的解决方案不会使问题消失,只会将发生率降低到约0.1%.好多了但远没有解决.我将使用阻塞读取替换异步读取,然后查看是否对其进行排序,如PaulF所建议的那样.
我有一个应用程序,通过套接字连接发送不同大小的可序列化对象,我希望它尽可能地扩展.也可能有数十甚至数百个连接.
所以似乎有太多的方法可以给这只猫留下光彩,而且我不确定什么才是最有效的.我是:
只需使用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) 我希望能够从C#中的TCP网络流中获取可用数据的长度,以便在从网络流中读取之前设置缓冲区的大小.有一个NetworkStream.Length属性但它还没有实现,我不想为缓冲区分配一个巨大的大小,因为它会占用太多的空间.我做这件事的唯一方法是在数据传输之前与另一个告诉大小,但这似乎有点混乱.这对我来说最好的方法是什么?
我正在尝试从已有配对代码和通信协议的医疗 BT 设备获取数据。
寻找一些代码我得到了这个代码:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using InTheHand.Net.Sockets;
using InTheHand.Net;
using InTheHand.Net.Bluetooth;
using InTheHand.Windows.Forms;
using System.Net.Sockets;
using System.Diagnostics;
using System.Threading;
namespace dConsoleApp
{
static class Program
{
// My BT USB adapter
private static BluetoothEndPoint EP = new BluetoothEndPoint(BluetoothAddress.Parse("00:02:72:CD:9A:33"), BluetoothService.BluetoothBase);
private static BluetoothClient BC = new BluetoothClient(EP);
// The BT device that would connect
private static BluetoothDeviceInfo BTDevice = new BluetoothDeviceInfo(BluetoothAddress.Parse("94:21:97:60:07:C0"));
private static NetworkStream stream = null;
static void Main(string[] args)
{
if (BluetoothSecurity.PairRequest(BTDevice.DeviceAddress, …Run Code Online (Sandbox Code Playgroud) 我目前正在使用tcp/ip套件.我正在编写一个程序来加密发送方端的文件,并在接收方进行解密.我在使用网络流的长度初始化我的字节数组时遇到了这个异常.这是我的代码:
if (client.Connected)
{
NetworkStream binarystream = client.GetStream();
byte[] receivebytes = new byte[binarystream.Length];
binarystream.Read(receivebytes, 0, receivebytes.Length);
Stream file = File.OpenWrite(saveFileDialog1.FileName);
file.Write(receivebytes, 0, receivebytes.Length);
file.Close();
binarystream.Close();
}
Run Code Online (Sandbox Code Playgroud)
控制层次结构确保client.GetStream()在构成二进制流实例之前已经使用了将返回的流.我得到的例外是包含以下内容的行:
byte[] receivebytes = new byte[binarystream.Length];
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.Read()阻塞线程.我有单独的线程在哪里NetworkStream.Read()等待来自服务器的数据.假设用户按下一些向服务器发送一些数据的按钮.但是在其他线程中等待数据NetworkStream.Write()时我无法调用NetworkStream.Read().我可以NetworkStream每次锁定但是NetworkStream.Read()会阻塞线程,所以在读取至少1个字节之前我不能发送数据.
我使用TcpClient和为游戏创建了一个简单的持久套接字连接NetworkStream。连接,发送消息和正常断开连接都没有问题(退出应用程序/服务器关闭/等)。
但是,在某些情况下,客户端无法检测到与服务器的断开连接时,我遇到了一些问题。我要测试的最简单方法是拔出wifi盒上的网络电缆,或将手机设置为飞行模式,但这是在游戏中发生的,否则应该是稳定的wifi。
仔细阅读NetworkStream等等的文档,它说检测到断开连接的唯一方法是尝试写入套接字。相当公平,除了,当我尝试时,写入通过就好像没有什么不对。我可以这样写多条消息,一切似乎都很好。只有当我重新插入电缆时,它才会断开连接(所有消息都已缓冲?)。
将TcpClient设置为NoDelay,Flush()无论如何每次写入后都会有一个被调用。
我尝试过的
NetworkStream-没有喜悦CanWrite,Connected等一切回归真实TcpClient.Client.Poll( 1000, SelectMode.SelectWrite ); -返回trueTcpClient.Client.Poll( 1000, SelectMode.SelectRead ) && TcpClient.Client.Available == 0 -返回trueTcpClient.Client.Receive(buffer, SocketFlags.Peek) == 0-连接时,阻塞约10-20s,然后返回true。当没有服务器时,永远阻塞(?)NetworkStream.Write() -不抛出错误NetworkStream.BeginWrite()-不会引发错误(即使在调用时也不会EndWrite())WriteTimeout-无效那我在这做错了吗?NetworkStream写入应断开连接的套接字时,是否有任何方法可以引发错误(如应有的错误)?
我对保持活动没有任何问题(默认情况下,服务器将通知客户端一段时间内未收到任何消息,并且客户端将发送心跳信号),但在几分钟内,根据NetworkStream一切笨拙的。
它是针对游戏的,因此理想情况下,检测应该足够快(因为用户仍然可以在游戏中移动,直到需要进行服务器调用为止,其中有些会阻塞UI,因此游戏似乎坏了)。
我正在使用Unity,所以它是.Net 2.0
networkstream ×10
c# ×9
tcp ×3
.net ×2
async-await ×2
sockets ×2
tcpclient ×2
.net-4.0 ×1
.net-4.5 ×1
32feet ×1
asynchronous ×1
bluetooth ×1
c#-5.0 ×1
serial-port ×1