代码之家  ›  专栏  ›  技术社区  ›  Cratylus

消息传递的java网络编程协调

  •  4
  • Cratylus  · 技术社区  · 14 年前

    我有两个进程在不同的机器上运行,它们通过TCP套接字进行通信。
    两个进程都有充当服务器和客户端的代码。
    即。 进程 已打开绑定在端口x和 过程B 已在portY打开服务器套接字绑定。
    ProcessA打开一个客户端套接字以连接ProcessB并开始作为客户端发送消息 以及接收响应(当然是通过同一个tcp连接)。
    一旦ProcessB接收到一条消息并对其进行处理,它就发送响应,但也可以通过第二个tcp连接发送消息,即ProcessB打开了一个客户端套接字到ProcessA的portX。
    所以消息流是通过两个不同的tcp连接。
    我的问题是: 理所当然地认为,这种“架构”不能改变,必须保持原样:
    我遇到的问题是,在ProcessB打开客户端套接字的tcp连接上,从ProcessB发送到ProcessA的消息间歇性地到达ProcessA,在ProcessA作为客户端套接字连接的tcp连接上,消息作为响应从ProcessB发送到ProcessA之前到达ProcessA。
    一、 e.两种流动都发生

    (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)
    

    编辑(在ejp请求之后) 在ProcessB的服务器portY将消息作为应答发送到ProcessA之前,如何强制/确保ProcessB不通过连接发送消息,即ProcessB有一个打开到ProcessA的服务器portX的客户端套接字?一、 e.只有上述流量(1)。
    请注意,processB是多线程的,而且处理过程非常重要。

    更新: 可能是我的误解,但是当进程通过套接字发送数据,并且控件返回给应用程序时,这并不意味着接收端已经接收到数据。 所以,如果一个进程通过两个套接字发送数据,操作系统是否存在竞争条件?

    更新2
    在得到维杰·马修的回答后:
    如果我按照建议进行了锁定,是否保证操作系统(即IP层)将按顺序发送数据?一、 完成一个传输,然后发送下一个?或者我会被多路复用并且有同样的问题吗?

    谢谢

    3 回复  |  直到 14 年前
        1
  •  1
  •   Vijay Mathew Chor-ming Lung    14 年前

    显而易见的解决方案是:

    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)
    }
    
        2
  •  1
  •   Paul Norris    13 年前

    同步问题可能不在TCP协议中,而在选择消息到达时唤醒哪个线程的线程处理程序中。我从你问题的本质上理解到,PortX“(Msg)”是在PortY“(Response)”之后很快发送的。这意味着线程处理程序有时可以选择它将唤醒的两个侦听线程中的哪一个。

    解决问题的一个简单但丑陋且不完整的方法是在响应和下一条消息之间插入一个简短的睡眠。睡眠时间必须足够长,以便确信在接收到下一条消息之前,另一个进程已经被响应唤醒。这种方式是不完整的,因为尽管您正在增加对正确同步处理的更改,但操作系统负载和网络拥塞等问题始终会合谋,将您的消息推回到您的响应后面。然后你又回到了起点。另一个丑陋的地方是睡觉浪费时间并且会减少你的最大吞吐量。只是不经常。所以。。。

    要完全解决这个问题,您需要为每个socket侦听器提供某种方法,以了解它刚刚接收到的消息是下一个要处理的消息,还是可能有更早的消息必须先处理。按顺序对每个进程发送的所有消息进行编号。然后接收过程知道是否丢失了什么。

    您必须考虑让每个套接字上的侦听器在它们之间进行协商的方法,以确保按照传输顺序处理接收到的消息。有许多实际的解决方案,但它们在抽象的概念层面上都是相同的。

    线程1: A) ProcessA(PortX)线程接收消息并唤醒。
    B) 如果序列号指示缺少消息,则 B1)进程上同步(PortY)并等待()。 B2)醒来时,回到B) C) {没有消息丢失}处理该消息。 D) 回到A)

    螺纹2: A) ProcessA(PortY)接收响应并唤醒。 B) 处理响应。 C) 通知全部()。 D) 回到A)

    最通用的实用解决方案可能涉及一个socket侦听器实例,它将所有新消息添加到PriorityQueue中,以便最早发送的消息始终到达队列的头部。然后线程1和线程2都可以在该实例上等待,直到消息到达,它们可以处理。

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

    祝你好运,尽管经过这么长时间,它可能已经解决了。

        3
  •  0
  •   user207421    14 年前

    显而易见的问题是你为什么在乎?如果有需要在两端同步的操作,请执行此操作。别指望TCP能帮你,那不是它的目的。