C# .NET新手套接字问题
我有一个C#客户机/服务器网络程序,我是用 TCPListener和TCPClient类。服务器正在读取所有内容 在我尝试发送 大文件(100k)返回到客户端 我正在使用流函数 客户端和服务器都具有非阻塞套接字功能。当我做一个 将socket.SendFile(“文件名”)返回到客户端,该文件将 切断-我已将客户端上的接收缓冲区大小设置为远远超过 100k,但仍在25k左右被切断,通讯中断 客户端和服务器之间的连接不可靠 我的基本问题 如果数据以某种方式留在管道中会发生什么?i、 是吗 通过下一个套接字读取。读取。。。是否每个发送呼叫都需要 只有一个人读?也许我没有给客户足够的时间 读了文件,但他们都在同一台机器上,我试过了C# .NET新手套接字问题,c#,.net,sockets,C#,.net,Sockets,我有一个C#客户机/服务器网络程序,我是用 TCPListener和TCPClient类。服务器正在读取所有内容 在我尝试发送 大文件(100k)返回到客户端 我正在使用流函数 客户端和服务器都具有非阻塞套接字功能。当我做一个 将socket.SendFile(“文件名”)返回到客户端,该文件将 切断-我已将客户端上的接收缓冲区大小设置为远远超过 100k,但仍在25k左右被切断,通讯中断 客户端和服务器之间的连接不可靠 我的基本问题 如果数据以某种方式留在管道中会发生什么?i、 是吗 通过下一
在不同的地方睡几秒钟,但没有成功。试着从服务器端分块发送数据块。正如另一位所说,发布代码将对我们有很大帮助。很可能您无法通过一个读取调用读取整个消息(可能所有数据尚未到达)。在网络编程中,您通常将Read调用放在while循环中,然后只需Read(),直到收到整个预期消息为止 您可能想要这样的东西:
socket.Blocking = false;
const int ChunkSize = 1492;
const int ReceiveTimeout = 10000;
const int SendTimeout = 10000;
public void Send(Byte[] data)
{
var sizeBytes = BitConverter.GetBytes(data.Length);
SendInternal(sizeBytes);
SendInternal(data);
}
public Byte[] Receive()
{
var sizeBytes = ReceiveInternal(4);
var size = BitConverter.ToInt32(sizeBytes, 0);
var data = ReceiveInternal(size);
return data;
}
private void SendInternal(Byte[] data)
{
var error = SocketError.Success;
var lastUpdate = Environment.TickCount;
var size = data.Length;
var count = 0;
var sent = 0;
while (sent < size)
{
count = Math.Min(ChunkSize, size - sent);
count = socket.Send(data, sent, count, SocketFlags.None, out error);
if (count > 0)
{
sent += count;
lastUpdate = Environment.TickCount;
}
if (error != SocketError.InProgress && error != SocketError.Success && error != SocketError.WouldBlock)
throw new SocketException((Int32)error);
if (Environment.TickCount - lastUpdate > SendTimeout)
throw new TimeoutException("Send operation timed out.");
if (count == 0 && !socket.Poll(100, SelectMode.SelectWrite))
throw new SocketException((Int32)SocketError.Shutdown);
}
}
private Byte[] ReceiveInternal(Int32 size)
{
var error = SocketError.Success;
var lastUpdate = Environment.TickCount;
var buffer = new Byte[ChunkSize];
var count = 0;
var received = 0;
using (var ms = new MemoryStream(size))
{
while (received < size)
{
count = Math.Min(ChunkSize, size - received);
count = socket.Receive(buffer, 0, count, SocketFlags.None, out error);
if (count > 0)
{
ms.Write(buffer, 0, count);
received += count;
lastUpdate = Environment.TickCount;
}
if (error != SocketError.InProgress && error != SocketError.Success && error != SocketError.WouldBlock)
throw new SocketException((Int32)error);
if (Environment.TickCount - lastUpdate > ReceiveTimeout)
throw new TimeoutException("Receive operation timed out.");
if (count == 0 && socket.Poll(100, SelectMode.SelectRead) && socket.Available == 0)
throw new SocketException((Int32)SocketError.Shutdown);
}
return ms.ToArray();
}
}
socket.Blocking=false;
常量int ChunkSize=1492;
const int ReceiveTimeout=10000;
const int SendTimeout=10000;
公共无效发送(字节[]数据)
{
var sizeBytes=BitConverter.GetBytes(data.Length);
SendInternal(大小字节);
发送内部(数据);
}
公共字节[]接收()
{
var sizeBytes=接收内部(4);
var size=BitConverter.ToInt32(sizeBytes,0);
var数据=接收内部(大小);
返回数据;
}
私有void SendInternal(字节[]数据)
{
var error=SocketError.Success;
var lastUpdate=Environment.TickCount;
变量大小=数据长度;
var计数=0;
var=0;
while(发送<大小)
{
count=Math.Min(ChunkSize,size-sent);
count=socket.Send(数据,已发送,计数,SocketFlags.None,out错误);
如果(计数>0)
{
发送+=计数;
lastUpdate=Environment.TickCount;
}
if(error!=SocketError.InProgress&&error!=SocketError.Success&&error!=SocketError.WouldBlock)
抛出新的SocketException((Int32)错误);
if(Environment.TickCount-lastUpdate>SendTimeout)
抛出新的TimeoutException(“发送操作超时”);
if(count==0&&!socket.Poll(100,SelectMode.SelectWrite))
抛出新的SocketException((Int32)SocketError.Shutdown);
}
}
专用字节[]接收内部(Int32大小)
{
var error=SocketError.Success;
var lastUpdate=Environment.TickCount;
var buffer=新字节[ChunkSize];
var计数=0;
收到的var=0;
使用(var ms=新内存流(大小))
{
while(接收<大小)
{
count=Math.Min(ChunkSize,size-received);
count=socket.Receive(缓冲区,0,count,SocketFlags.None,out错误);
如果(计数>0)
{
ms.Write(缓冲区,0,计数);
接收+=计数;
lastUpdate=Environment.TickCount;
}
if(error!=SocketError.InProgress&&error!=SocketError.Success&&error!=SocketError.WouldBlock)
抛出新的SocketException((Int32)错误);
if(Environment.TickCount-lastUpdate>ReceiveTimeout)
抛出新的TimeoutException(“接收操作超时”);
if(count==0&&socket.Poll(100,SelectMode.SelectRead)&&socket.Available==0)
抛出新的SocketException((Int32)SocketError.Shutdown);
}
返回ToArray女士();
}
}
1个发送呼叫可能需要多个读取呼叫才能接收,1个读取呼叫可能读取多个发送呼叫发送的数据
TCP只是提供了一个流,因此您可以定义如何对发送的数据或消息进行分区
在这种情况下,您可能只需要循环,一直读到流关闭。我通常会创建一个发送的头结构
Header Size (int, 4 bytes)
File Name Offset (int, 4 bytes)
File Name Size (int , 4 bytes)
File Data Offset (int, 4 bytes)
File Data Size (int , 4 bytes)
[ message data here]
然后使用二进制读取器或使用封送将字节复制到结构中来读取该标头。通过这种方式,您总是知道到达的数据以及需要调用Read()的次数
header size字段也有助于对协议进行版本控制(保持结构不变,但为以后的客户端添加,以便保持向后兼容性)。如果在C#中定义结构,请确保这样做:
[StructLayout LayoutKind.Sequential]
struct MessageHeader
{
public int HeaderSize;
public int FileNameOffset;
public int FileNameSize;
public int FileDataOffset;
public int FileDataSize;
}
然后,
Marshal.PtrToStructure
将允许您从套接字读取的字节[]创建此结构的实例换行符使文本更易于阅读。您可以为客户端和服务器提供代码吗?如果可以,发布一些代码。如果不了解您实现了什么,就很难回答您的问题。请参阅以获取一些相关的答案。添加一个指定传入消息长度的标题:while(readBuffer
,或者,如果您只想读取每个连接发送的所有数据,请使用以下代码: