2010-11-18 29 views
4

我有2个进程在不同的机器上运行,这些机器通过TCP套接字进行通信。
这两个进程的代码既可以作为服务器,也可以作为客户端。
I.e. ProcessA已打开一个服务器套接字,该端口绑定在端口X上,并且ProcessB已在端口Y上打开服务器套接字绑定。
ProcessA打开一个客户端套接字与ProcessB连接并开始以客户端 发送消息并接收响应(当然通过相同的tcp连接)。 ProcessB一旦接收到消息并对其进行处理,它就发送响应,但也可以通过第二个TCP连接发送消息,即ProcessB已经打开了一个客户端套接字到ProcessA的portX。
所以消息流是通过2个不同的TCP连接。
我的问题是这样的:以作为理所当然地认为,这个“建筑”不能改变,必须保持原样:
我有间歇性,消息来自进程B发送到ProcessA通过TCP连接是进程B有问题打开客户端套接字,在消息通过ProcessA作为客户端套接字连接的tcp连接作为从ProcessB到ProcessA的响应发送之前到达processA。
I.e.这两个流发生java网络编程协调消息传递

EDIT(后EJP要求)
(1) 
ProcessA ---->(msg)----> ProcessB(PortY) (TCP1) 
ProcessB does processing 
ProcessB(portY)--->(response)----->ProcessA (TCP1) 
ProcessB--->(msg)----->ProcessA(portX) (TCP2) 

(2) 
ProcessA ---->(msg)----> ProcessB(PortY) (TCP1) 
ProcessB does processing 
ProcessB--->(msg)----->ProcessA(portX) (TCP2) 
ProcessB(portY)--->(response)----->ProcessA (TCP1) 

我如何可以强制执行/确保进程B不超过该进程B有一个客户端套接字开放ProcessA的服务器端口X,之前连接发送味精从ProcessB的服务器portY发送的消息作为回复发送到processA?即只有上述流程(1)。
请注意,processB是多线程的,处理是非平凡的。

UPDATE: 可能是我的错觉,但是当一个进程通过套接字发送数据,并控制返回到应用程序,这并不意味着接收方已经接收到的数据。 因此,如果一个进程通过2个套接字发送数据,OS是否存在竞争条件?

UPDATE2
答案,我从维杰马修拿到后:
如果我做了一个锁定的建议,是有保证的是OS(即IP层)会为了发送数据?即完成一次传输,然后发送下一个?或者我会将它们复用并具有相同的问题?

感谢

+0

你能澄清吗?你的意思是B不应该通过portX发送* next *请求给A,直到*前一个*答复已经通过端口X从A到达了?所以Y港口在这里完全不相关? – EJP 2010-11-18 08:08:26

+0

@ejp:有2个tcp连接。 B不应该通过端口X向A发送消息(在A中打开),而是在A收到之前消息的回复(由A发送给在端口Y上监听的B)之前由A接收。这是否更清楚?所以portY并不是无关紧要的。 A发送的第一个消息是tcp连接。 – Cratylus 2010-11-18 08:13:54

+0

你的段落开头'我怎么能确保'根本没有提到港口Y.所以它不同意你刚才说的。你能把所有这些变成协议吗?所以我认为B端口不应该在端口X上发送任何东西,而在端口Y上有待处理的回复。反过来也是如此吗? – EJP 2010-11-18 10:01:32

回答

1

显而易见的解决方案是:

LockObject lock; 

ProcessA ---->(msg)----> ProcessB(PortY) 

// Processing the request and sending its response 
// makes a single transaction. 
synchronized (lock) { 
    ProcessB does processing 
    ProcessB(portY)--->(response)----->ProcessA (TCP1) 
} 

// While the processing code holds the lock, B is not 
// allowed to send a request to A. 
synchronized (lock) { 
    ProcessB--->(msg)----->ProcessA(portX) (TCP2) 
} 
+0

也许这是我的误解,但是当processB将数据通过套接字切换到OS时,数据被另一端收到后,控制权是否会从OS返回到应用程序?不,所以OS可以缓冲数据,ProcessB将移动到第二个锁,然后通过第二个套接字传递数据。所以还是会有一些竞争条件,在2送之中,对吧? – Cratylus 2010-11-18 06:56:55

0

最明显的问题是,为什么你关心吗?如果您有需要同步的操作,请执行此操作。不要期望TCP为你做,这不是它的目的。

+0

同步如何? – Cratylus 2010-11-19 06:20:03

+0

同步为什么? – EJP 2010-11-19 09:03:56

+0

我不确定你的建议。我想知道,例如我是否遵循了Vijay Mathew的建议,由于数据传输的方式,我仍然会遇到竞争状况。操作系统会缓冲这两个数据,并通过电线将它们复用发送 – Cratylus 2010-11-19 09:15:50

1

同步问题可能不在TCP协议中,而是在线程处理程序中选择消息到达时要唤醒哪个线程。根据您的问题的性质,我明白PortX“(Msg)”在PortY之后发送非常快(“响应”)。这意味着线程处理程序偶尔可以选择它将唤醒的两个侦听线程中的哪一个。

解决此问题的一种简单但丑陋且不完整的方法是在响应和下一条消息之间插入一段短暂的睡眠。睡眠时间必须足够长,以确信在接收到下一条消息之前其他进程已经唤醒响应。这种方式并不完整,因为虽然您正在增加正确同步处理的更改,但操作系统负载和网络拥塞等问题始终可能会导致您的消息回到响应背后。然后你回到你开始的地方。另一个丑陋的地方是睡觉浪费时间,并会减少你的最大吞吐量。不太经常。因此...

要完全解决此问题,您需要一些方法让每个套接字侦听器知道它刚收到的消息是下一个要处理的消息还是可能存在必须处理的早期消息第一。按顺序编号由每个进程发送的所有消息。然后接收过程知道是否有遗漏。

您将不得不想办法让每个套接字上的侦听器在它们自己之间进行协商,以确保接收到的邮件按传输顺序进行处理。有许多实际的解决方案,但它们在抽象概念层面上都是相同的。

线程1: A)ProcessA(PortX)线程收到消息并唤醒。 B)如果序列号指示存在缺失的消息,则B1)在ProcessA(PortY)和wait()上同步。 B2)醒来后,返回B) C){没有消息丢失}处理消息。 D)返回A)

线程2: A)ProcessA(PortY)接收响应并唤醒。 B)处理响应。 C)notifyAll()。 D)返回A)

最通用的实际解决方案可能会涉及一个单一的套接字侦听器实例,将所有新消息添加到PriorityQueue中,以便最早发送的消息总是进入队列头部。然后,线程1和线程2都可以在该实例上等待,直到消息到达,他们可以处理。

一个更简单但不易扩展的解决方案是让每个线程都自己监听并等待处理后通知(响应)处理程序。

祝你好运,虽然毕竟这一次,它可能已经解决了。