【发布时间】:2013-02-26 08:08:04
【问题描述】:
我在 C# 的 TCP 之上编写了一个专有协议(客户端和服务器),它将文件从客户端发送到服务器,反之亦然。
由于概念上是全双工的,因此客户端和服务器的接收和发送方法是相同的。
该协议允许client1 将文件上传到server,一旦文件被缓冲(在服务器上),client1 可以决定是否client2 和/或client3 获取文件。 (server 可以只发送给client2,只发送给client3,或者同时发送给两者,这取决于client1 的请求)。
问题是我看到服务器 -> 客户端的数据传输速度很慢,大约 140 kb/s,而客户端的实际带宽要高得多,服务器显然也是如此。
起初我以为这只是这个特定连接的最大带宽(我家的客户端和远程位置的服务器),但后来我看到当我打开 @ 时传输速率翻倍 987654330@ 和 client3 在我的电脑上,让服务器同时向它们发送文件;每个客户端都保持不变,但由于它们都在同一台 PC 上,我的本地网络上的总吞吐量翻了一番。
- 对我的问题可能在哪里有任何想法?如何将服务器 -> 客户端传输速率提高到最大值?
- 任何关于我的代码的一般改进点都将受到高度赞赏。
这是我的代码:
struct ReceiveBuffer
{
public const int BUFFER_SIZE = 1024 * 16;
public byte[] BUFFER;
public int ToReceive;
public MemoryStream BufStream;
public ReceiveBuffer(int toRec)
{
BUFFER = new byte[BUFFER_SIZE];
ToReceive = toRec;
BufStream = new MemoryStream(toRec);
}
}
struct SendBuffer
{
public const int BUFFER_SIZE = 1024 * 16;
public byte[] BUFFER;
public int sent;
public SendBuffer(byte[] data)
{
BUFFER = new byte[data.Length];
Buffer.BlockCopy(data, 0, BUFFER, 0, data.Length);
sent = 0;
}
}
public void ReceiveAsync()
{
try
{
socket.BeginReceive(lenBuffer, 0, 4, SocketFlags.None,
receiveCallback, null);
}
catch (SocketException se)
{
//handle disconnection
}
}
void receiveCallback(IAsyncResult ar)
{
try
{
int rec = socket.EndReceive(ar);
if (rec == 0)
{
if (Disconnected != null)
{
Disconnected(this);
return;
}
}
if (rec != 4)
{
//less than 4 bytes received...error
return;
}
receiveBuffer = new ReceiveBuffer(BitConverter.ToInt32(lenBuffer, 0));
socket.BeginReceive(receiveBuffer.BUFFER, 0,
receiveBuffer.BUFFER.Length,
SocketFlags.None, receivePacketCallback, null);
}
catch (SocketException se)
{
//raise disconnection event
}
}
void receivePacketCallback(IAsyncResult ar)
{
try
{
int rec = socket.EndReceive(ar);
if (rec <= 0)
{
return;
}
receiveBuffer.BufStream.Write(receiveBuffer.BUFFER, 0, rec);
receiveBuffer.ToReceive -= rec;
if (receiveBuffer.ToReceive > 0)
{
Array.Clear(receiveBuffer.BUFFER, 0, receiveBuffer.BUFFER.Length);
socket.BeginReceive(receiveBuffer.BUFFER, 0,
receiveBuffer.BUFFER.Length,
SocketFlags.None, receivePacketCallback, null);
return;
}
if (DataReceived != null)
{
//raise dataReceived event
}
receiveBuffer.Dispose();
if (socket !=null)
ReceiveAsync();
}
catch (SocketException se)
{
//handle disconnection
}
}
// Send Async
public void SendAsyncString(string str, CommandsToClient cmd)
{
BinaryWriter bw = new BinaryWriter(new MemoryStream());
bw.Write((int)cmd);
bw.Write((int)str.Length);
bw.Write(Encoding.ASCII.GetBytes(str));
bw.Close();
byte[] data = ((MemoryStream)(bw.BaseStream)).ToArray();
bw.BaseStream.Dispose();
SendAsync(data);
}
public void SendAsync(byte[] data)
{
int toSend;
byte[] dataWithHeader = Combine(BitConverter.GetBytes(data.Length), data);
sendBuffer = new SendBuffer(dataWithHeader);
if (sendBuffer.BUFFER.Length - sendBuffer.sent > SendBuffer.BUFFER_SIZE)
toSend = SendBuffer.BUFFER_SIZE;
else
toSend = sendBuffer.BUFFER.Length - sendBuffer.sent;
socket.BeginSend(sendBuffer.BUFFER, 0,toSend, SocketFlags.None,
sendCallback, null);
}
void sendCallback(IAsyncResult ar)
{
try
{
int bytesSent = socket.EndSend(ar);
if (bytesSent == 0)
{
//raise disconnection event
}
sendBuffer.sent += bytesSent;
if (sendBuffer.sent==sendBuffer.BUFFER.Length)
{
sendBuffer.Dispose();
return;
}
int toSend;
if (sendBuffer.BUFFER.Length - sendBuffer.sent > SendBuffer.BUFFER_SIZE)
toSend = SendBuffer.BUFFER_SIZE;
else
toSend = sendBuffer.BUFFER.Length - sendBuffer.sent;
socket.BeginSend(sendBuffer.BUFFER, sendBuffer.sent,toSend,
SocketFlags.None, sendCallback, null);
}
catch (SocketException se)
{
//hande disconnection
}
}
【问题讨论】:
-
您确定要编写自己的专有协议吗?你不能使用现有的东西吗?
-
@BasileStarynkevitch,是的。我还没有找到适合我需要的协议。
-
这一切都可以通过几个现有的协议来完成。
-
@Daniel - Heyup。我查看了您的代码,没有发现任何明显的问题。我认为 Basile 可能意味着您是否考虑过使用网络库?
-
@MarcF 感谢马克的回答。我不明白为什么我不应该在 TCP 之上编写自己的协议。从我见过的所有协议来看,没有人给我真正需要的东西。无论如何,问题似乎是缓冲区大小。我会为其他人正确回答...
标签: c# sockets networking tcp client-server