- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我正在尝试编写客户端/服务器文件传输系统。目前它可以工作,我已经对它进行了分析,而且我发送数据的速度似乎不能超过每秒 2-4 兆字节。我已经调整了我的代码,以便我可以每秒数百兆字节的速度从磁盘读取数据,并且性能向导显示我的磁盘读取和我的套接字写入之间没有超过 1-3,所以我的代码设置(它似乎)以与 nic/cpu/主板一样快的速度推出数据,无论什么都能处理它。
我想问题是,为什么不是这样呢?
这是一些代码,以便您了解我在这里设置的内容。
namespace Skylabs.Net.Sockets
{
public abstract class SwiftSocket
{
public TcpClient Sock { get; set; }
public NetworkStream Stream { get; set; }
public const int BufferSize = 1024;
public byte[] Buffer = new byte[BufferSize];
public bool Connected { get; private set; }
private Thread _thread;
private bool _kill = false;
protected SwiftSocket()
{
Connected = false;
Sock = null;
_thread = new Thread(Run);
}
protected SwiftSocket(TcpClient client)
{
_Connect(client);
}
public bool Connect(string host, int port)
{
if (!Connected)
{
TcpClient c = new TcpClient();
try
{
c.Connect(host, port);
_Connect(c);
return true;
}
catch (SocketException e)
{
return false;
}
}
return false;
}
public void Close()
{
_kill = true;
}
private void _Connect(TcpClient c)
{
Connected = true;
Sock = c;
Stream = Sock.GetStream();
_thread = new Thread(Run);
_thread.Name = "SwiftSocketReader: " + c.Client.RemoteEndPoint.ToString();
_thread.Start();
}
private void Run()
{
int Header = -1;
int PCount = -1;
List<byte[]> Parts = null;
byte[] sizeBuff = new byte[8];
while (!_kill)
{
try
{
Header = Stream.ReadByte();
PCount = Stream.ReadByte();
if (PCount > 0)
Parts = new List<byte[]>(PCount);
for (int i = 0; i < PCount; i++)
{
int count = Stream.Read(sizeBuff, 0, 8);
while (count < 8)
{
sizeBuff[count - 1] = (byte)Stream.ReadByte();
count++;
}
long pieceSize = BitConverter.ToInt64(sizeBuff, 0);
byte[] part = new byte[pieceSize];
count = Stream.Read(part, 0, (int)pieceSize);
while (count < pieceSize)
{
part[count - 1] = (byte)Stream.ReadByte();
}
Parts.Add(part);
}
HandleMessage(Header, Parts);
Thread.Sleep(10);
}
catch (IOException)
{
Connected = false;
if(System.Diagnostics.Debugger.IsAttached)System.Diagnostics.Debugger.Break();
break;
}
catch (SocketException)
{
Connected = false;
if (System.Diagnostics.Debugger.IsAttached) System.Diagnostics.Debugger.Break();
break;
}
}
HandleDisconnect();
}
public void WriteMessage(int header, List<byte[]> parts)
{
try
{
byte[] sizeBuffer = new byte[8];
//Write header byte
Stream.WriteByte((byte)header);
if (parts == null)
Stream.WriteByte((byte)0);
else
{
Stream.WriteByte((byte)parts.Count);
foreach (byte[] p in parts)
{
sizeBuffer = BitConverter.GetBytes(p.LongLength);
//Write the length of the part being sent
Stream.Write(sizeBuffer, 0, 8);
Stream.Write(p, 0, p.Length);
//Sock.Client.Send(p, 0, p.Length, SocketFlags.None);
}
}
}
catch (IOException)
{
if (System.Diagnostics.Debugger.IsAttached) System.Diagnostics.Debugger.Break();
_kill = true;
}
catch (SocketException)
{
if (System.Diagnostics.Debugger.IsAttached) System.Diagnostics.Debugger.Break();
_kill = true;
}
}
protected void WriteMessage(int header)
{
WriteMessage(header,null);
}
public abstract void HandleMessage(int header, List<byte[]> parts);
public abstract void HandleDisconnect();
}
}
namespace Skylabs.Breeze
{
public class FileTransferer
{
public String Host { get; set; }
public string FileName { get; set; }
public string FilePath { get; set; }
public string Hash { get; set; }
public FileStream File { get; set; }
public List<TransferClient> Clients { get; set; }
public const int BufferSize = 1024;
public int TotalPacketsSent = 0;
public long FileSize{get; private set; }
public long TotalBytesSent{get; set; }
private int clientNum = 0;
public int Progress
{
get
{
return (int)(((double)TotalBytesSent / (double)FileSize) * 100d);
}
}
public event EventHandler OnComplete;
public FileTransferer()
{
}
public FileTransferer(string fileName, string host)
{
FilePath = fileName;
FileInfo f = new FileInfo(fileName);
FileName = f.Name;
Host = host;
TotalBytesSent = 0;
try
{
File = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read, BufferSize, FileOptions.SequentialScan);
File.Lock(0,File.Length);
}
catch (Exception e)
{
ErrorWindow er = new ErrorWindow(e);
er.ShowDialog();
}
}
public bool Grab_Next_Data_Chunk(ref byte[] buffer, out int size, out long pos)
{
lock (File)
{
pos = File.Position;
size = 0;
if (pos >= FileSize - 1)
return false;
int count = File.Read(buffer, 0, (FileSize - pos) >= FileTransferer.BufferSize ? FileTransferer.BufferSize : (int)(FileSize - pos));
//TotalBytesSent += count;
size = count;
TotalPacketsSent++;
return true;
}
}
public bool Start(int ConnectionCount)
{
Program.ServerTrace.TraceInformation("Creating Connections.");
if (Create_Connections(ConnectionCount) == false)
{
return false;
}
File.Seek(0, SeekOrigin.Begin);
FileSize = File.Length;
Clients[0].Start(this,0);
List<byte[]> parts = new List<byte[]>(1);
parts.Add(BitConverter.GetBytes(FileSize));
Clients[0].WriteMessage((int)Program.Message.CFileStart, parts);
Program.ServerTrace.TraceInformation("Sent start packet");
for (clientNum = 1; clientNum < ConnectionCount; clientNum++)
{
Clients[clientNum].Start(this, clientNum);
}
return true;
}
private bool Create_Connections(int count)
{
Clients = new List<TransferClient>();
for (int i = 0; i < count; i++)
{
TransferClient tc = new TransferClient();
if (tc.Connect(Host, 7678) == false)
return false;
Clients.Add(tc);
}
return true;
}
public void AddClient()
{
TransferClient tc = new TransferClient();
tc.Connect(Host, 7678);
tc.Start(this, clientNum);
clientNum++;
Clients.Add(tc);
}
public void RemoveClient()
{
Clients.Last().Kill();
}
public void AdjustClientCount(int newCount)
{
int dif = newCount - Clients.Count;
if (dif > 0)
{
for(int i=0;i<dif;i++)
AddClient();
}
else
{
for(int i=0;i<Math.Abs(dif);i++)
RemoveClient();
}
}
public void ClientDone(TransferClient tc)
{
List<byte[]> parts = new List<byte[]>(1);
parts.Add(ASCIIEncoding.ASCII.GetBytes(FileName));
tc.WriteMessage((int)Program.Message.CPartDone,parts);
tc.Close();
Clients.Remove(tc);
if (Clients.Count == 0)
{
Program.ServerTrace.TraceInformation("File '{0}' Transfered.\nTotal Packets Sent: {1}", FilePath,
TotalPacketsSent);
File.Unlock(0,File.Length);
File.Close();
File.Dispose();
if(OnComplete != null)
OnComplete.Invoke(this,null);
}
}
}
public class TransferClient : Skylabs.Net.Sockets.SwiftSocket,IEquatable<TransferClient>
{
public FileTransferer Parent;
public int ID;
private bool KeepRunning = true;
public Thread Runner;
public void Start(FileTransferer parent, int id)
{
this.Sock.Client.
Parent = parent;
ID = id;
List<byte[]> p = new List<byte[]>(1);
p.Add(Encoding.ASCII.GetBytes(Parent.FileName));
WriteMessage((int)Program.Message.CHello, p);
}
public void Kill()
{
KeepRunning = false;
}
private void run()
{
while (KeepRunning)
{
List<Byte[]> p = new List<byte[]>(3);
byte[] data = new byte[FileTransferer.BufferSize];
int size = 0;
long pos = 0;
if (Parent.Grab_Next_Data_Chunk(ref data,out size,out pos))
{
p.Add(data);
p.Add(BitConverter.GetBytes(size));
p.Add(BitConverter.GetBytes(pos));
WriteMessage((int)Program.Message.CData, p);
Parent.TotalBytesSent += size;
}
else
{
break;
}
Thread.Sleep(10);
}
Parent.ClientDone(this);
}
public bool Equals(TransferClient other)
{
return this.ID == other.ID;
}
public override void HandleMessage(int header, List<byte[]> parts)
{
switch (header)
{
case (int)Program.Message.SStart:
{
Runner = new Thread(run);
Runner.Start();
break;
}
}
}
public override void HandleDisconnect()
{
//throw new NotImplementedException();
}
}
}
我想强调的是,在 FileTransferer.Get_Next_Data_Chunk 中几乎没有延迟,它的读取速度非常快,每秒数百兆字节。此外,我认为套接字的 WriteMessage 是流线型和快速的。
也许有什么设置?还是不同的协议(protocol)?
我们非常欢迎任何想法。
我忘了说,这个程序是专门为 LAN 环境构建的,它的最大速度为 1000Mbps(或字节,我不确定,如果有人也能澄清这一点,那也很好。)
最佳答案
首先,您的网络速度将是每秒比特数,几乎不是每秒字节数。
其次,您可能会受到 IO 阅读器不断打开和关闭文件的限制。除非您在 SSD 上运行,否则由于驱动器寻道时间,这将导致开销显着增加。
要解决这个问题,请尝试将缓冲区大小增加到更大的值 1024
很小。我通常使用 262144
左右(256K) 用于我的缓冲区大小。
除此之外,您还需要像这样管道化文件 IO:
ReadBlock1
loop while block length > 0
TransmitBlock1 in separate thread
ReadBlock2
Join transmit thread
end loop
使用上述管道,您通常可以将传输速度提高一倍。
当您实现流水线文件 IO 时,您不再需要担心缓冲区大小过大的问题,除非您的文件总是大小为 < 2 * BufferSize
。 ,因为您说您正在处理超过 100mb 的文件,所以您不必担心这种情况。
您可以做的其他改进是使用 .
还要记住,在 .NET 中,尽管使用了线程,文件 IO 通常是同步的。
如需进一步阅读,请参阅:http://msdn.microsoft.com/en-us/library/kztecsys.aspx
编辑:只是补充一下,如果您认为问题出在网络而不是文件 IO,那么只需注释掉网络部分,使其立即出现,那么您的速度是多少?反过来呢,如果你让你的文件读取总是返回一个空的new byte[BufferSize]
怎么办?这对您的复制速度有何影响?
关于c# slow socket 速度,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8321271/
基于 socket.io 的官方网站 http://socket.io/#how-to-use , 我找不到任何术语。socket.emit 、 socket.on 和 socket.send 之间有
我正在使用 lua-socket 3.0rc1.3(Ubuntu Trusty 附带)和 lua 5.1。我正在尝试监听 unix 域套接字,我能找到的唯一示例代码是 this -- send std
这两者有什么区别? 我注意到如果我在一个工作程序中从 socket.emit 更改为 socket.send ,服务器无法接收到消息,虽然我不明白为什么。 我还注意到,在我的程序中,如果我从 sock
使用套接字在两台服务器之间发送数据是个好主意,还是应该使用 MQ 之类的东西来移动数据。 我的问题:套接字是否可靠,如果我只需要一次/有保证的数据传输? 还有其他解决方案吗? 谢谢。 最佳答案 套接字
引自 this socket tutorial : Sockets come in two primary flavors. An active socket is connected to a
我已经安装了在端口81上运行的流服务器“Lighttpd”(light-tpd)。 我有一个C程序,它使用套接字api创建的服务器套接字在端口80上监听http请求。 我希望从客户端收到端口80上的请
这是我正在尝试做的事情: 当有新消息可用时,服务器会将消息发送给已连接的客户端。另一方面,客户端在连接时尝试使用send()向服务器发送消息,然后使用recv()接收消息,此后,客户端调用close(
如何将消息发送到动态 session 室,以及当服务器收到该消息时,如何将该消息发送到其他成员所在的同一个 session 室? table_id是房间,它将动态设置。 客户: var table_i
这是我尝试但不起作用的方法。我可以将传入的消息从WebSocket连接转发到NetSocket,但是只有NetSocket收到的第一个消息才到达WebSocket后面的客户端。 const WebSo
我正在实现使用boost将xml发送到客户端的服务器。我面临的问题是缓冲区不会立即发送并累积到一个点,然后发送整个内容。这在我的客户端造成了一个问题,当它解析xml时,它可能具有不完整的xml标记(不
尝试使用Nginx代理Gunicorn套接字。 /etc/systemd/system/gunicorn.service文件 [Unit] Description=gunicorn daemon Af
我正在使用Lua套接字和TCP制作像聊天客户端和服务器这样的IRC。我要弄清楚的主要事情是如何使客户端和服务器监听消息并同时发送它们。由于在服务器上执行socket:accept()时,它将暂停程序,
我看了一下ZMQ PUSH/PULL套接字,尽管我非常喜欢简单性(特别是与我现在正在通过UDP套接字在系统中实现的自定义碎片/ack相比),但我还是希望有自定义负载平衡功能,而不是幼稚的回合-robi
我正在编写一个应用程序,其中有多个 socket.io 自定义事件,并且所有工作正常,除了这个: socket.on("incomingImg", function(data) {
在我的应用程序中,我向服务器发送了两条小消息(类似 memcached 的服务)。在类似 Python 的伪代码中,这看起来像: sock.send("add some-key 0") ignored
很抱歉再次发布此问题,但大多数相关帖子都没有回答我的问题。我在使用 socket.io 的多个连接时遇到问题我没有使用“socket.socket.connect”方法,但我从第一次连接中得到了反馈。
我尝试使用 socket.io 客户端连接到非 socket.io websocket 服务器。但我做不到。我正在尝试像这样连接到套接字服务器: var socket = io.connect('ws
我遇到了一个奇怪的问题。在我非常基本的服务器中,我有: server.listen(8001); io.listen(server); var sockets = io.sockets; 不幸的是,套
我正在使用带套接字 io 的sailsjs。帆的版本是 0.10.5。我有以下套接字客户端进行测试: var socketIOClient = require('socket.io-client');
这个问题在这里已经有了答案: What is the fundamental difference between WebSockets and pure TCP? (4 个答案) 关闭 4 年前。
我是一名优秀的程序员,十分优秀!