我不是网络专家所以请耐心等待。我需要在两台计算机之间建立一个非常简单的单向数据连接,每隔100ms就会使用一个整数来转移整数(int8或int16),从计算机A到计算机B.连接和数据传输总是在方向A - >; B.由于我想尽快对@ B中的软件包做出反应,我想知道我应该使用哪种协议来最小化网络延迟。也就是说,我希望转移尽可能“实时”,理想情况是延迟是< 10毫秒(如果可能的话,任何包裹都不会丢失)。
以下是我的具体问题:
计算机A和B连接到同一个交换机,并且物理上非常靠近并且为了减少不必要的“网络噪声”,计算机可以与网络的其余部分分开。
非常感谢示例代码:)
答案 0 :(得分:2)
数目:
哪种通讯协议适合这项工作?
这取决于您的应用程序对数据包丢失的容忍度与延迟抖动(延迟可变性)。在您的本地单一交换机配置中,无论您使用何种传输方式,您可能都不会遇到其中任何一个问题,但如果您的网络变得嘈杂,或者您可能决定将其扩展到更大的网络上,那么您将需要决定哪个更重要。如果避免丢包是您的最高优先级,那么您应该使用基于会话的传输(TCP,WebSockets)。如果避免延迟抖动是至关重要的,那么您可能希望使用UDP传输。例如,大多数在线FPS游戏都使用UDP,因为偶尔丢包或重新排序是可以接受的,但延迟抖动不是。
这种延迟是我试图实现的吗?
是的,请参阅下一个答案。
理论上我可以达到的最小延迟是多少?
在本地单一交换机网络上,绝对可以将平均延迟时间设置为10毫秒。如果您使用端到端千兆以太网,则可能会达到平均单向延迟低于0.1毫秒(100微秒)。
延迟是否会严重依赖于所使用的交换机?或者任何便宜的消费者转换都可以吗?
切换肯定会影响您的延迟。然而,即使是便宜的100 Mb / s消费者交换机也应该让你不到10毫秒(可能甚至不到1毫秒)。
如果我需要突然发送更多数据,为了最大限度地减少开销,最佳封装尺寸是多少?
作为一般规则,通过使用不会被分段的最大有效负载将实现最低开销。但是你必须考虑端到端的碎片。例如,你的网卡和切换所有支持巨型帧(大于1500字节)?他们都有相同的MTU设置吗?您的传输库是否具有任意缓冲大小?
实际测量延迟的最佳/正确方法是什么?
我建议创建一个延迟测试应用程序,该应用程序包含您打算使用的实际硬件和所有整个软件堆栈,并构建延迟测试应用程序以测试实际的实际延迟(不仅仅是理论上的)。您将需要测试往返延迟然后除以2(否则您将花费所有时间进行高精度时间同步)。此外,您还希望能够轻松调整有效负载大小,尤其是当您想要回答有关最有效的程序包/消息大小的上一个问题时。如果您正在考虑使用UDP,那么我还建议在您的有效负载中添加序列号并检查它们以确保您没有遇到任何意外的数据包丢失或重新排序(重新排序不应该在一个交换机上发生网络)。
如果您要使用大型有效负载/包,那么我还强烈建议您使用wireshark来查看线路上实际发生的情况。您应该能够轻松识别正在发生的任何碎片(这是了解网络协议如何工作的一种很好的方式)。
延迟取决于使用的编程语言多少? (我考虑java,c,python)
语言的选择当然可以产生非平凡的差异。但是,在你的单一交换机本地网络案例中,我怀疑python是足够的,因为它应该远低于边缘。在Java和Python中,套接字代码是用C / C ++实现的,因此只要没有对数据进行过多的预处理或后处理,额外的开销就不会太明显了。在我看来,使用python或Java的更大风险是你的应用程序对延迟抖动很敏感。 Java和python都是垃圾收集语言,并且根据应用程序的性质,这会在有效延迟中引入意外的抖动(即,在语言运行时垃圾收集时偶尔会出现暂停)。
我个人会从python开始,因为开发是如此迅速(但从最有效的开始)然后切换到C,如果性能结果是一个问题。此外,如果您的项目有可能被纳入更大的生态系统,那么您应该选择该生态系统中的首选语言。
使用TCP的优点和缺点是什么?
优点:保证按顺序交付所有数据。
缺点:需要更多初始设置。对于复杂或嘈杂的网络环境,可能会因重试和重新排序而产生延迟抖动。
使用UDP的优点和缺点是什么?
优点:低延迟。
缺点:只有尽力而为。可以丢弃和/或重新排序分组。跨防火墙可能更复杂。
使用websockets的优点和缺点是什么?
优点:允许浏览器成为您的终点之一,否则与TCP相同(它是TCP上的传输分层)。它是基于消息的传输,因此不需要重新组装数据(例如,您在发送消息时会收到完整的消息)。
缺点:对于每条消息,都有像握手一样的HTTP和一些最小的框架。
这是python中的一个简单的往返回显客户端和服务器:
服务器:
# Echo server program
import socket, sys
while True:
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind(('', int(sys.argv[1])))
s.listen(1)
conn, addr = s.accept()
print 'Connected by', addr
while True:
data = conn.recv(1024)
if not data: break
conn.sendall(data)
conn.close()
客户端:
# Echo client program
import socket, sys, time
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((sys.argv[1], int(sys.argv[2])))
i = 0
while True:
i += 1
start = time.time()
s.sendall('Test payload #%d' % i)
data = s.recv(1024)
end = time.time()
print "%f-%f" % (end, start)
print "Received '%s' back in %f milliseconds" % (data,
(end-start)*1000.0)
time.sleep(0.5)
在服务器主机上,运行:
python ./server.py 8123
在您的客户端主机上,运行:
python ./client.py SERVER_HOST 8123
答案 1 :(得分:0)
您可以使用TCP进行此操作。只需确保B
在收到每个整数后将应用程序级别的确认发送回A
。这将允许ACK捎带数据,确保下一次传输不会延迟。延迟应该不到1毫秒。
答案 2 :(得分:0)
给出那些非常理想的网络条件,我认为UDP非常适合这项任务(数据丢失应该非常罕见,以至于TCP是一种过度杀伤)。
答案 3 :(得分:0)
如果我理解正确,要求应该很容易满足。实际上,您应该可以获得< 1ms
延迟。一个简单/粗略的测试是在两台计算机之间使用ping
来大致了解时间。
对于实现,我会使用TCP / IP。它使得可靠性更容易实现(比UDP更简单)并且相对容易实现。您可能希望禁用Nagle算法(setsockopt( ... TCP_NODELAY ...)
)以消除此类小数据包通常会发生的延迟。
答案 4 :(得分:0)
我认为您正在寻找的解决方案是客户端服务器架构中的TCP套接字。 由于你没有说明编程语言的选择,我首先在Python中尝试概念验证,然后(如果它太慢)切换到普通的C或C ++(使用提到的一个库{{3 }})。
另外,请查看here的延迟和套接字。