2016-11-12 39 views
1

在Java和C#我用双工插座通信以能够由具有读取从阻挡流传入的数据包,和其他线程以同步的功能上发送分组的螺纹很容易写双向套接字通信。C++与ASIO

例如东西沿着线:

class MyBidirectionalSocket { 
    private OutputStream output; 

    public MyBidirectionalSocket(Socket socket) { 
     output = new BufferedOutputStream(socket.getOutputStream()); 
     new ReadingThread(socket).start(); 
    } 

    public synchronized void sendPacket(MyPacket packet) { 
     output.write(packet.getBytes()); 
     output.flush(); 
    } 

    private class ReadingThread extends Thread { 
     private InputStream input; 

     private ReadingThread(Socket socket) { 
      input = socket.getInputStream(); 
     } 

     public void run() { 
      // real code would catch EOF exceptions, IO exceptions, etc... 
      while (true) { 
       MyPacket packet = readPacketFromStream(input); 
       doSomethingWithPacket(packet); 
      } 
     } 
    } 
} 

总是工作很适合我,因为我可以从输入流只是读数据,而不必费心当数据到达约实现readPacketFromStream - 它只是阻塞,直到数据可用,或者如果流被关闭,则抛出EOFException(或IOException),这可以在后面找到。如果我想要高吞吐量,我甚至可以沿着各种工作线程分发传入数据包。

现在我的问题是 - 我希望做类似的事情,在C++中,具有跨平台实现。但是如何?

我一直在学习Boost库,因为这些似乎得到广泛的应用,有很多的功能。它们基本上提供了两种与套接字进行通信的方式,一种是面向流的阻塞(使用套接字iostreams),另一种是使用异步套接字通信(Boost asio)。

阻塞方法似乎只工作半双工,因为iostream的不是线程安全的(这多线程应用程序可以和会写,并在同一时间阅读!)。因此,据我所知,这是没有选择的。

在我的情况下,异步方法似乎是最好的选择。但是,我将收到大量的数据 - 可能包含数据包,半数据包或多个数据包,或其任何组合。 理想情况下,我会将接收到的数据存储到流中,然后单独的线程可以执行阻止读取。

因此我的问题:

1)是否这样的多线程“管道”流在C++中的存在,无论是在标准库,以升压,或其他地方?我当然不是世界上第一个需要这种东西的人,所以我怀疑它一定存在,尽管我找不到它。

2)可替换地,有另一种图案 - 使用升压或另一多平台库 - 可以被用于实现类似于上面的代码的机制?

+1

你可以用'asio'做同步读写。为了避免线程之间的任何种族问题,你可以使用'asio :: strand'。但是,你必须更好地了解'asio'才能实现这个想法。前往'asio'文档并通过它的例子。 – Arunmu

+0

我跟着这些 - http://www.boost.org/doc/libs/1_62_0/doc/html/boost_asio/tutorial.html。尽管我明白你对种族问题的含义,但我仍然有将输入数据“重构”为可同步读取的数据流的问题,并且从教程中不清楚如何处理该问题。 –

+0

我不认为我理解“将传入数据重构为可同步读取的数据流”。您的处理程序将对'asio :: socket'进行同步读取,将其写入'buffer',该文件可以是'array'或'string'或'asio :: streambuf'。您不必为套接字创建单独的“流”。将java程序行到行转换为C++没有意义。这可能是非常低效的代码。 – Arunmu

回答

0

boost :: asio非常灵活。您可以将它用于同步操作(阻塞直到数据发送或接收)或异步操作(您开始读取/写入操作并在完成后会在特定线程上进行回调)。您甚至可以将两者混合使用,例如异步读取并同步写入。

如果你想按照你的Java模型尽可能靠近你可以简单地粘到ASIO提供同步操作。

这意味着,如果你有一个像

shared_ptr<boost::asio::ip::tcp::socket> socket; 

插座时启动一个额外的线程,使用阻塞读取从那里socket->read(...),可能写入套接字从另一个线程与socket->write(...)。这是绝对安全的,只要你不做两个并发读取。对于并发写入,您可能需要额外的互斥锁。

请注意,这个同步写入/读取仅仅是一个非常小的包装在本地OS套接字API的允许相同。 asios power主要是以异步变体的形式出现的(但是看起来不同于你的Java代码,因此可能不太理想)。所以你甚至可以使用本地套接字。

关于ASIO上级包装,ip::tcp::iostream stream: 可惜我也不知道这是否是线程安全与否,是否可以在相同的双向配置被用作同步插座即可。但我会期待它,因为否则对于大多数应用程序来说它将毫无价值。

+0

最后,我使用了异步方法,我编程将数据存储在缓冲区中,直到收到完整的数据包。无论哪种方式,感谢您的意见,它证实了我不确定的事情,并且至少我处于了解我的选择的阶段。也感谢@Arunmu。 –