⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ncbi_namedpipe.cpp

📁 ncbi源码
💻 CPP
📖 第 1 页 / 共 3 页
字号:
/* * =========================================================================== * PRODUCTION $Log: ncbi_namedpipe.cpp,v $ * PRODUCTION Revision 1000.5  2004/06/01 18:45:01  gouriano * PRODUCTION PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.26 * PRODUCTION * =========================================================================== *//*  $Id: ncbi_namedpipe.cpp,v 1000.5 2004/06/01 18:45:01 gouriano Exp $ * =========================================================================== * *                            PUBLIC DOMAIN NOTICE *               National Center for Biotechnology Information * *  This software/database is a "United States Government Work" under the *  terms of the United States Copyright Act.  It was written as part of *  the author's official duties as a United States Government employee and *  thus cannot be copyrighted.  This software/database is freely available *  to the public for use. The National Library of Medicine and the U.S. *  Government have not placed any restriction on its use or reproduction. * *  Although all reasonable efforts have been taken to ensure the accuracy *  and reliability of the software and data, the NLM and the U.S. *  Government do not and cannot warrant the performance or results that *  may be obtained by using this software or data. The NLM and the U.S. *  Government disclaim all warranties, express or implied, including *  warranties of performance, merchantability or fitness for any particular *  purpose. * *  Please cite the author in any work or product based on this material. * * =========================================================================== * * Author:  Anton Lavrentiev, Mike DiCuccio, Vladimir Ivanov * * File Description: *   Portable interprocess named pipe API for:  UNIX, MS-Win * */#include <ncbi_pch.hpp>#include <connect/ncbi_namedpipe.hpp>#include <corelib/ncbi_system.hpp>#if defined(NCBI_OS_MSWIN)#elif defined(NCBI_OS_UNIX)#  include <unistd.h>#  include <errno.h>#  include <fcntl.h>#  include <errno.h>#  include <sys/socket.h>#  include <sys/stat.h>#  include <sys/time.h>#  include <sys/un.h>#  include <connect/ncbi_socket.h>#else#  error "Class CNamedPipe is supported only on Windows and Unix"#endifBEGIN_NCBI_SCOPE#if !defined(HAVE_SOCKLEN_T)typedef int socklen_t;#endif// Predefined timeoutsconst size_t kDefaultPipeBufSize = (size_t)CNamedPipe::eDefaultBufSize;////////////////////////////////////////////////////////////////////////////////// Auxiliary functions//static STimeout* s_SetTimeout(const STimeout* from, STimeout* to){    if ( !from ) {        return const_cast<STimeout*> (kInfiniteTimeout);    }    to->sec  = from->usec / 1000000 + from->sec;    to->usec = from->usec % 1000000;    return to;}static string s_FormatErrorMessage(const string& where, const string& what){    return "[NamedPipe::" + where + "]  " + what + ".";}inline void s_AdjustPipeBufSize(size_t* bufsize) {    if (*bufsize == 0)        *bufsize = kDefaultPipeBufSize;    else if (*bufsize == (size_t)kMax_Int)        *bufsize = 0 /* use system default buffer size */;}////////////////////////////////////////////////////////////////////////////////// Class CNamedPipeHandle handles forwarded requests from CNamedPipe.// This class is reimplemented in a platform-specific fashion where needed.//#if defined(NCBI_OS_MSWIN)const DWORD kSleepTime = 100;  // sleep time for timeouts////////////////////////////////////////////////////////////////////////////////// CNamedPipeHandle -- MS Windows version//class CNamedPipeHandle{public:    CNamedPipeHandle(void);    ~CNamedPipeHandle(void);    // client-side    EIO_Status Open(const string& pipename, const STimeout* timeout,                    size_t pipebufsize);    // server-side    EIO_Status Create(const string& pipename, size_t pipebufsize);    EIO_Status Listen(const STimeout* timeout);    EIO_Status Disconnect(void);    // common    EIO_Status Close(void);    EIO_Status Read(void* buf, size_t count, size_t* n_read,                    const STimeout* timeout);    EIO_Status Write(const void* buf, size_t count, size_t* n_written,                     const STimeout* timeout);    EIO_Status Wait(EIO_Event event, const STimeout* timeout);    EIO_Status Status(EIO_Event direction) const;private:    long TimeoutToMSec(const STimeout* timeout) const;private:    HANDLE      m_Pipe;         // pipe I/O handle    string      m_PipeName;     // pipe name     size_t      m_PipeBufSize;  // pipe buffer size    EIO_Status  m_ReadStatus;   // last read status    EIO_Status  m_WriteStatus;  // last write status};CNamedPipeHandle::CNamedPipeHandle(void)    : m_Pipe(INVALID_HANDLE_VALUE), m_PipeName(kEmptyStr),      m_PipeBufSize(0),      m_ReadStatus(eIO_Closed), m_WriteStatus(eIO_Closed){    return;}CNamedPipeHandle::~CNamedPipeHandle(void){    Close();}EIO_Status CNamedPipeHandle::Open(const string&   pipename,                                  const STimeout* timeout,                                  size_t          /* pipebufsize */){    try {        if (m_Pipe != INVALID_HANDLE_VALUE) {            throw string("Pipe is already open");        }        // Save parameters        m_PipeName    = pipename;        m_PipeBufSize = 0 /* pipebufsize is not used on client side */;        // Set the base security attributes        SECURITY_ATTRIBUTES attr;        attr.nLength = sizeof(attr);        attr.bInheritHandle = TRUE;        attr.lpSecurityDescriptor = NULL;        // Waits until either a time-out interval elapses or an instance of        // the specified named pipe is available for connection (that is, the        // pipe's server process has a pending Listen() operation on the pipe).        // NOTE: We do not use here a WaitNamedPipe() because it works        //       incorrect in some cases.        DWORD x_timeout = TimeoutToMSec(timeout);        do {            // Open existing pipe            m_Pipe = CreateFile(pipename.c_str(),                                GENERIC_READ | GENERIC_WRITE,                                FILE_SHARE_READ | FILE_SHARE_WRITE,                                &attr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL,                                NULL);            if (m_Pipe != INVALID_HANDLE_VALUE) {                m_ReadStatus  = eIO_Success;                m_WriteStatus = eIO_Success;                return eIO_Success;            }            DWORD x_sleep = kSleepTime;            if (x_timeout != INFINITE) {                if (x_timeout < kSleepTime) {                    x_sleep = x_timeout;                }                x_timeout -= x_sleep;            }            SleepMilliSec(x_sleep);        } while (x_timeout == INFINITE  ||  x_timeout);        return eIO_Timeout;    }    catch (string& what) {        Close();        ERR_POST(s_FormatErrorMessage("Open", what));        return eIO_Unknown;    }}EIO_Status CNamedPipeHandle::Create(const string& pipename,                                    size_t        pipebufsize){    try {        if (m_Pipe != INVALID_HANDLE_VALUE) {            throw string("Pipe is already open");        }        // Save parameters        m_PipeName    = pipename;        m_PipeBufSize = pipebufsize;        // Set the base security attributes        SECURITY_ATTRIBUTES attr;        attr.nLength = sizeof(attr);        attr.bInheritHandle = TRUE;        attr.lpSecurityDescriptor = NULL;        // Create pipe        m_Pipe = CreateNamedPipe(                 pipename.c_str(),              // pipe name                  PIPE_ACCESS_DUPLEX,            // read/write access                  PIPE_TYPE_BYTE | PIPE_NOWAIT,  // byte-type, nonblocking mode                  1,                             // one instance only                  pipebufsize,                   // output buffer size                  pipebufsize,                   // input buffer size                  INFINITE,                      // client time-out by default                 &attr);                        // security attributes        if (m_Pipe == INVALID_HANDLE_VALUE) {            throw "Create named pipe \"" + pipename + "\" failed";        }        m_ReadStatus  = eIO_Success;        m_WriteStatus = eIO_Success;        return eIO_Success;    }    catch (string& what) {        Close();        ERR_POST(s_FormatErrorMessage("Create", what));        return eIO_Unknown;    }}EIO_Status CNamedPipeHandle::Listen(const STimeout* timeout){    EIO_Status status = eIO_Unknown;    // Wait for the client to connect, or time out.    // NOTE: The function WaitForSingleObject() do not work with pipes.    DWORD x_timeout = TimeoutToMSec(timeout);    try {        if (m_Pipe == INVALID_HANDLE_VALUE) {            status = eIO_Closed;            throw string("Pipe is closed");        }        do {            BOOL connected = ConnectNamedPipe(m_Pipe, NULL);            if ( !connected ) {                DWORD error = GetLastError();                connected = (error == ERROR_PIPE_CONNECTED);                 // If client closed connection before we serve it                if (error == ERROR_NO_DATA) {                    if (Disconnect() != eIO_Success) {                        throw string("Listening pipe: failed to close broken "                                     "client session");                    }                 }            }            if ( connected ) {                return eIO_Success;            }            DWORD x_sleep = kSleepTime;            if (x_timeout != INFINITE) {                if (x_timeout < kSleepTime) {                    x_sleep = x_timeout;                }                x_timeout -= x_sleep;            }            SleepMilliSec(x_sleep);        } while (x_timeout == INFINITE  ||  x_timeout);        return eIO_Timeout;    }    catch (string& what) {        ERR_POST(s_FormatErrorMessage("Listen", what));        return status;    }}EIO_Status CNamedPipeHandle::Disconnect(void){    EIO_Status status = eIO_Unknown;    try {        if (m_Pipe == INVALID_HANDLE_VALUE) {            status = eIO_Closed;            throw string("Pipe is already closed");        }        FlushFileBuffers(m_Pipe);         if (!DisconnectNamedPipe(m_Pipe)) {            throw string("DisconnectNamedPipe() failed");        }         Close();        return Create(m_PipeName, m_PipeBufSize);    }    catch (string& what) {        ERR_POST(s_FormatErrorMessage("Disconnect", what));        return status;    }}EIO_Status CNamedPipeHandle::Close(void){    if (m_Pipe == INVALID_HANDLE_VALUE) {        return eIO_Closed;    }    FlushFileBuffers(m_Pipe);    CloseHandle(m_Pipe);    m_Pipe = INVALID_HANDLE_VALUE;    m_ReadStatus  = eIO_Closed;    m_WriteStatus = eIO_Closed;    return eIO_Success;}EIO_Status CNamedPipeHandle::Read(void* buf, size_t count, size_t* n_read,                                  const STimeout* timeout){    EIO_Status status = eIO_Unknown;    try {        if (m_Pipe == INVALID_HANDLE_VALUE) {            status = eIO_Closed;            throw string("Pipe is closed");        }        if ( !count ) {			m_ReadStatus = eIO_Success;            return m_ReadStatus;        }        DWORD x_timeout   = TimeoutToMSec(timeout);        DWORD bytes_avail = 0;        // Wait a data from the pipe with timeout.        // NOTE:  The function WaitForSingleObject() do not work with pipe.        do {            if ( !PeekNamedPipe(m_Pipe, NULL, 0, NULL, &bytes_avail, NULL) ) {                // Peer has been closed the connection?                if (GetLastError() == ERROR_BROKEN_PIPE) {					m_ReadStatus = eIO_Closed;                    return m_ReadStatus;                }                throw string("Cannot peek data from the named pipe");            }            if ( bytes_avail ) {                break;            }            DWORD x_sleep = kSleepTime;            if (x_timeout != INFINITE) {                if (x_timeout < kSleepTime) {                    x_sleep = x_timeout;                }                x_timeout -= x_sleep;            }            SleepMilliSec(x_sleep);        } while (x_timeout == INFINITE  ||  x_timeout);        // Data is available to read or time out        if ( !bytes_avail ) {			m_ReadStatus = eIO_Timeout;            return m_ReadStatus;        }        // We must read only "count" bytes of data regardless of the number        // available to read        if (bytes_avail > count) {            bytes_avail = count;        }        if (!ReadFile(m_Pipe, buf, count, &bytes_avail, NULL)) {            throw string("Failed to read data from the named pipe");        }        if ( n_read ) {            *n_read = bytes_avail;        }        status = eIO_Success;    }    catch (string& what) {        ERR_POST(s_FormatErrorMessage("Read", what));    }    m_ReadStatus = status;    return status;}EIO_Status CNamedPipeHandle::Write(const void* buf, size_t count,                                   size_t* n_written, const STimeout* timeout){    EIO_Status status = eIO_Unknown;    try {        if (m_Pipe == INVALID_HANDLE_VALUE) {            status = eIO_Closed;            throw string("Pipe is closed");        }        if ( !count ) {            return eIO_Success;        }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -