windows channel
来源:互联网 发布:图片放去噪算法 编辑:程序博客网 时间:2024/06/11 22:38
BlockQueue.h
#pragma once#include "Common.h"#include "Condition.h"template<typename T>class BlockQueue{public:BlockQueue(): mutex_(), notEmpty_(mutex_){}void put(const T &t){MutexLockGuard lock(mutex_);queue_.push_back(t);notEmpty_.notify();}T take(){MutexLockGuard lock(mutex_);while (queue_.empty()) {notEmpty_.wait();}assert(!queue_.empty());T front(queue_.front());queue_.pop_front();return front;}size_t size() const{MutexLockGuard lock(mutex_);return queue_.size(); }private:BlockQueue(const BlockQueue&);BlockQueue& operator=(const BlockQueue&);private:mutable MutexLock mutex_;Condition notEmpty_;std::deque<T> queue_;};
Buffer.h
#pragma once#include "Common.h"class Buffer;typedef std::tr1::shared_ptr<Buffer> BufferPtr;class Buffer{public: static const size_t kCheapPrepend = 8; static const size_t kInitialSize = 2048; Buffer() : buffer_(kCheapPrepend + kInitialSize) , readerIndex_(kCheapPrepend) , writerIndex_(kCheapPrepend){assert(readableBytes() == 0);assert(writableBytes() == kInitialSize);assert(prependableBytes() == kCheapPrepend);}void swap(Buffer &rhs){buffer_.swap(rhs.buffer_);std::swap(readerIndex_, rhs.readerIndex_);std::swap(writerIndex_, rhs.writerIndex_);}size_t readableBytes() const{return writerIndex_ - readerIndex_; }size_t writableBytes() const{return buffer_.size() - writerIndex_;}size_t prependableBytes() const{return readerIndex_;}const char *peek() const{return begin() + readerIndex_;}void retrieve(size_t len){assert(len <= readableBytes());if ( len < readableBytes()){readerIndex_ += len;}else{retrieveAll();}}void retrieveUntil(const char *end){assert(peek() <= end);assert(end <= beginWrite());retrieve(end - peek());}void retrieveInt32(){retrieve(sizeof(__int32));}void retrieveInt16(){retrieve(sizeof(__int16));}void retrieveInt8(){retrieve(sizeof(__int8));}void retrieveAll(){readerIndex_ = kCheapPrepend;writerIndex_ = kCheapPrepend;}std::string retrieveAllAsString(){return retrieveAsString(readableBytes());}std::string retrieveAsString(size_t len){assert(len <= readableBytes());std::string result(peek(), len);retrieve(len);return result;}void append(const std::string &str){append(str.c_str(), str.size());}void append(const char* data, size_t len){ensureWritableBytes(len);std::copy(data, data+len, stdext::checked_array_iterator<char*>(beginWrite(), len));hasWritten(len);}void append(const void* data, size_t len){append(static_cast<const char*>(data), len);}void ensureWritableBytes(size_t len){if (writableBytes() < len){makeSpace(len);}assert(writableBytes() >= len);}char* beginWrite(){return begin() + writerIndex_;}const char* beginWrite() const{return begin() + writerIndex_;}void hasWritten(size_t len){writerIndex_ += len;}void appendInt32(__int32 x);void appendInt16(__int16 x);void appendInt8(__int8 x);__int32 readInt32();__int16 readInt16();__int8 readInt8();__int32 peekInt32() const;__int16 peekInt16() const;__int8 peekInt8() const;void prependInt32(__int32 x);void prependInt16(__int16 x);void prependInt8(__int8 x);bool Buffer::read(void* data, size_t len){if (data && readableBytes() >= len){memcpy(data, peek(), len);retrieve(len);return true;}return false;}void prepend(const void* data, size_t len){assert(len <= prependableBytes());readerIndex_ -= len;const char *d = static_cast<const char*>(data);std::copy(d, d+len, stdext::checked_array_iterator<char*>(begin()+readerIndex_, len));}int readFd(void* fd, int *saveErrno);private:char *begin(){return &*buffer_.begin();}const char* begin() const{return &*buffer_.begin();}void makeSpace(size_t len){if (writableBytes() + prependableBytes() < len + kCheapPrepend){buffer_.resize(writerIndex_ + len);}else{assert(kCheapPrepend < readerIndex_);size_t readable = readableBytes();std::copy(begin() + readerIndex_, begin() + writerIndex_,stdext::checked_array_iterator<char*>(begin() + kCheapPrepend, writerIndex_ - readerIndex_));readerIndex_ = kCheapPrepend;writerIndex_ = readerIndex_ + readable;assert(readable == readableBytes());}}Buffer(const Buffer&);const Buffer& operator=(const Buffer&);private:std::vector<char> buffer_;size_t readerIndex_;size_t writerIndex_;};
Channel.h
#pragma once#include "Buffer.h"#include "BlockQueue.h"#define TCPCONN_SUCCESS0#define TCPCONN_ERROR_BASE0x00100#define TCPCONN_ERROR_SOCKETTCPCONN_ERROR_BASE + 1#define TCPCONN_ERROR_CONNECTTCPCONN_ERROR_BASE + 2#define TCPCONN_ERROR_SENDTCPCONN_ERROR_BASE + 3#define TCPCONN_ERROR_RECVTCPCONN_ERROR_BASE + 4#define TCPCONN_ERROR_WSAEVENTSELECTTCPCONN_ERROR_BASE + 5#define TCPCONN_ERROR_WSAENUMNETWORKEVENTSTCPCONN_ERROR_BASE + 6#define TCPCONN_ERROR_WSAWAITFORMULTIPLEEVENTSTCPCONN_ERROR_BASE + 7typedef std::tr1::function<void(Buffer&)> OnReadCallback;typedef std::tr1::function<void(int)> OnErrorCallback;typedef std::tr1::function<void()> OnCloseCallback;class Connector;class Thread;template<typename T> class BlockQueue;typedef std::tr1::shared_ptr<Connector> ConnectorPtr;class Channel{public:Channel(ConnectorPtr connectorPtr);~Channel();void start();void stop();void send(const unsigned char *msg, size_t len);void send(const BufferPtr &msg);void setOnReadCallback(const OnReadCallback &cb) { onReadCallback_ = cb; }void setOnErrorCallback(const OnErrorCallback &cb) { onErrorCallback_ = cb; }void setOnCloseCallback(const OnCloseCallback &cb) { onCloseCallback_ = cb; }private:Channel(const Channel&);Channel& operator=(const Channel&);void sendBufferThread();void recvBufferThread();private:ConnectorPtr connectorPtr_;scoped_ptr<Thread> recvBufferThread_;scoped_ptr<Thread> sendBufferThread_;scoped_ptr<BlockQueue<BufferPtr> > sendQueue_;Buffer recvBuffer_;OnReadCallback onReadCallback_;OnErrorCallback onErrorCallback_;OnCloseCallback onCloseCallback_;};
Common.h
#pragma once#include <assert.h>#include <stdlib.h>#include <cstddef>#include <string.h>#include <memory>#include <functional>#include <string>#include <deque>#include <algorithm>#include <vector>#include <map>#include <iterator>#include <WinSock2.h>#include <Windows.h>#include <iostream> // for testnamespace internal {// This is an implementation designed to match the anticipated future TR2// implementation of the scoped_ptr class, and its closely-related brethren,// scoped_array, scoped_ptr_malloc, and make_scoped_ptr.template <class C> class scoped_ptr;template <class C> class scoped_array;// A scoped_ptr<T> is like a T*, except that the destructor of scoped_ptr<T>// automatically deletes the pointer it holds (if any).// That is, scoped_ptr<T> owns the T object that it points to.// Like a T*, a scoped_ptr<T> may hold either NULL or a pointer to a T object.//// The size of a scoped_ptr is small:// sizeof(scoped_ptr<C>) == sizeof(C*)template <class C>class scoped_ptr { public: // The element type typedef C element_type; // Constructor. Defaults to intializing with NULL. // There is no way to create an uninitialized scoped_ptr. // The input parameter must be allocated with new. explicit scoped_ptr(C* p = NULL) : ptr_(p) { } // Destructor. If there is a C object, delete it. // We don't need to test ptr_ == NULL because C++ does that for us. ~scoped_ptr() { enum { type_must_be_complete = sizeof(C) }; delete ptr_; } // Reset. Deletes the current owned object, if any. // Then takes ownership of a new object, if given. // this->reset(this->get()) works. void reset(C* p = NULL) { if (p != ptr_) { enum { type_must_be_complete = sizeof(C) }; delete ptr_; ptr_ = p; } } // Accessors to get the owned object. // operator* and operator-> will assert() if there is no current object. C& operator*() const { assert(ptr_ != NULL); return *ptr_; } C* operator->() const { assert(ptr_ != NULL); return ptr_; } C* get() const { return ptr_; } // Comparison operators. // These return whether two scoped_ptr refer to the same object, not just to // two different but equal objects. bool operator==(C* p) const { return ptr_ == p; } bool operator!=(C* p) const { return ptr_ != p; } // Swap two scoped pointers. void swap(scoped_ptr& p2) { C* tmp = ptr_; ptr_ = p2.ptr_; p2.ptr_ = tmp; } // Release a pointer. // The return value is the current pointer held by this object. // If this object holds a NULL pointer, the return value is NULL. // After this operation, this object will hold a NULL pointer, // and will not own the object any more. C* release() { C* retVal = ptr_; ptr_ = NULL; return retVal; } private: C* ptr_; // Forbid comparison of scoped_ptr types. If C2 != C, it totally doesn't // make sense, and if C2 == C, it still doesn't make sense because you should // never have the same object owned by two different scoped_ptrs. template <class C2> bool operator==(scoped_ptr<C2> const& p2) const; template <class C2> bool operator!=(scoped_ptr<C2> const& p2) const; // Disallow evil constructors scoped_ptr(const scoped_ptr&); void operator=(const scoped_ptr&);};// scoped_array<C> is like scoped_ptr<C>, except that the caller must allocate// with new [] and the destructor deletes objects with delete [].//// As with scoped_ptr<C>, a scoped_array<C> either points to an object// or is NULL. A scoped_array<C> owns the object that it points to.//// Size: sizeof(scoped_array<C>) == sizeof(C*)template <class C>class scoped_array { public: // The element type typedef C element_type; // Constructor. Defaults to intializing with NULL. // There is no way to create an uninitialized scoped_array. // The input parameter must be allocated with new []. explicit scoped_array(C* p = NULL) : array_(p) { } // Destructor. If there is a C object, delete it. // We don't need to test ptr_ == NULL because C++ does that for us. ~scoped_array() { enum { type_must_be_complete = sizeof(C) }; delete[] array_; } // Reset. Deletes the current owned object, if any. // Then takes ownership of a new object, if given. // this->reset(this->get()) works. void reset(C* p = NULL) { if (p != array_) { enum { type_must_be_complete = sizeof(C) }; delete[] array_; array_ = p; } } // Get one element of the current object. // Will assert() if there is no current object, or index i is negative. C& operator[](std::ptrdiff_t i) const { assert(i >= 0); assert(array_ != NULL); return array_[i]; } // Get a pointer to the zeroth element of the current object. // If there is no current object, return NULL. C* get() const { return array_; } // Comparison operators. // These return whether two scoped_array refer to the same object, not just to // two different but equal objects. bool operator==(C* p) const { return array_ == p; } bool operator!=(C* p) const { return array_ != p; } // Swap two scoped arrays. void swap(scoped_array& p2) { C* tmp = array_; array_ = p2.array_; p2.array_ = tmp; } // Release an array. // The return value is the current pointer held by this object. // If this object holds a NULL pointer, the return value is NULL. // After this operation, this object will hold a NULL pointer, // and will not own the object any more. C* release() { C* retVal = array_; array_ = NULL; return retVal; } private: C* array_; // Forbid comparison of different scoped_array types. template <class C2> bool operator==(scoped_array<C2> const& p2) const; template <class C2> bool operator!=(scoped_array<C2> const& p2) const; // Disallow evil constructors scoped_array(const scoped_array&); void operator=(const scoped_array&);};} // namespace internal// We made these internal so that they would show up as such in the docs,// but we don't want to stick "internal::" in front of them everywhere.using internal::scoped_ptr;using internal::scoped_array;
Condition.h
#pragma once#include "MutexLock.h"class Condition{public:explicit Condition(MutexLock &mutex): mutex_(mutex){InitializeConditionVariable(&cond_);}void wait(){SleepConditionVariableCS(&cond_, &mutex_.cs(), INFINITE);}void notify(){WakeConditionVariable(&cond_);}private:Condition(const Condition&);Condition& operator=(const Condition&);private:MutexLock &mutex_;CONDITION_VARIABLE cond_;};
Connector.h
#pragma once#include "Common.h"class Connector{public:typedef std::tr1::function<void(SOCKET fd)> ConnectionCallback;Connector(const std::string &ip, unsigned short port);virtual ~Connector(void);virtual void start();virtual void stop();void setConnectionCallback(const ConnectionCallback &func) { func_ = func; }SOCKET socket() const { return sock_; }bool connected() const { return connected_; }private:void connect();private:std::string ip_;unsigned short port_;ConnectionCallback func_;SOCKET sock_;bool connected_;};
MutexLock.h
#pragma once#include <WinBase.h>class MutexLock{public:MutexLock(){InitializeCriticalSection(&criticalSection_);}~MutexLock(){DeleteCriticalSection(&criticalSection_);}void lock(){EnterCriticalSection(&criticalSection_);}void unlock(){LeaveCriticalSection(&criticalSection_);}CRITICAL_SECTION& cs(){return criticalSection_;}private:MutexLock(const MutexLock&);MutexLock& operator=(const MutexLock&);CRITICAL_SECTION criticalSection_;};class MutexLockGuard{public:explicit MutexLockGuard(MutexLock &mutex): mutex_(mutex){mutex_.lock();}~MutexLockGuard(){mutex_.unlock();}private:MutexLockGuard(const MutexLockGuard&);MutexLockGuard operator=(const MutexLockGuard&);MutexLock& mutex_;};
Thread.h
#pragma once#include "Common.h"class Thread{public:typedef std::tr1::function<void()> ThreadFunc;explicit Thread(const ThreadFunc&, const std::string &name=std::string());~Thread();void start();int join();bool started() const { return started_; }HANDLE handle() const { return handle_; }unsigned int tid() const { return tid_; }const std::string& name() const { return name_; }private:static unsigned int WINAPI startThread(void *data);void runInThread();private:HANDLE handle_;unsigned int tid_;bool started_;ThreadFunc func_;std::string name_;};
WSAStartup.h
#pragma onceclass WsaStartup{public:WsaStartup(unsigned char majorVer, unsigned char minorVer);virtual ~WsaStartup(void);};Buffer.cpp
#include "Buffer.h"#include <WinSock2.h>void Buffer::appendInt32(__int32 x){__int32 be32 = htonl(x);append(&be32, sizeof(be32));}void Buffer::appendInt16(__int16 x){__int16 be16 = htons(x);append(&be16, sizeof(be16));}void Buffer::appendInt8(__int8 x){append(&x, sizeof(x));}__int32 Buffer::readInt32(){__int32 result = peekInt32();retrieveInt32();return result;}__int16 Buffer::readInt16(){__int16 result = peekInt16();retrieveInt16();return result;}__int8 Buffer::readInt8(){__int8 result = peekInt8();retrieveInt8();return result;}__int32 Buffer::peekInt32() const{assert(readableBytes() >= sizeof(__int32));__int32 be32 = 0;::memcpy(&be32, peek(), sizeof(be32));return ntohl(be32);}__int16 Buffer::peekInt16() const{assert(readableBytes() >= sizeof(__int16));__int16 be16 = 0;::memcpy(&be16, peek(), sizeof(be16));return htons(be16);}__int8 Buffer::peekInt8() const{assert(readableBytes() >= sizeof(__int8));__int8 x = *peek();return x;}void Buffer::prependInt32(__int32 x){__int32 be32 = htonl(x);prepend(&be32, sizeof(be32));}void Buffer::prependInt16(__int16 x){__int16 be16 = htons(x);prepend(&be16, sizeof(be16));}void Buffer::prependInt8(__int8 x){prepend(&x, sizeof(x));}int Buffer::readFd(void* fd, int *saveErrno){SOCKET sock = (SOCKET)fd;int writable = writableBytes();int n = ::recv(sock, begin() + writerIndex_, writable, 0);if (SOCKET_ERROR == n){*saveErrno = WSAGetLastError();}else if (n <= writable){writerIndex_ += n;}return n;}
Channel.cpp
#include "Channel.h"#include "Thread.h"#include "Connector.h"Channel::Channel(ConnectorPtr connectorPtr): connectorPtr_(connectorPtr), sendQueue_(new BlockQueue<BufferPtr>()){recvBufferThread_.reset(new Thread(std::tr1::bind(&Channel::recvBufferThread, this), "eventHandleThread"));sendBufferThread_.reset(new Thread(std::tr1::bind(&Channel::sendBufferThread, this), "sendBufferThread"));}Channel::~Channel(void){}void Channel::start(){connectorPtr_->start();recvBufferThread_->start();sendBufferThread_->start();}void Channel::stop(){connectorPtr_->stop();BufferPtr lastBufferPtr(new Buffer());sendQueue_->put(lastBufferPtr);recvBufferThread_->join();sendBufferThread_->join();sendQueue_.reset(new BlockQueue<BufferPtr>());}void Channel::send(const unsigned char *msg, size_t len){BufferPtr bufferPtr(new Buffer());bufferPtr->append(msg, len);sendQueue_->put(bufferPtr);}void Channel::send(const BufferPtr &msg){sendQueue_->put(msg);}void Channel::sendBufferThread(){std::cout << "recvBufferThread" << std::endl;while (connectorPtr_->connected()) {BufferPtr bufferPtr = sendQueue_->take();if (!connectorPtr_->connected()) {break;}unsigned int left = bufferPtr->readableBytes();while (left > 0) {int sendNum = ::send(connectorPtr_->socket(), bufferPtr->peek(), left, 0);if (SOCKET_ERROR == sendNum) {onErrorCallback_(TCPCONN_ERROR_SEND);break;}left -= sendNum;bufferPtr->retrieve(sendNum);}}std::cout << "recvBufferThread exit" << std::endl;}void Channel::recvBufferThread(){std::cout << "sendBufferThread" << std::endl;while (connectorPtr_->connected()) {static const int bufferLen = 65535;;char buffer[bufferLen];int recvNum = ::recv(connectorPtr_->socket(), buffer, bufferLen, 0);if (recvNum > 0) {recvBuffer_.append(buffer, recvNum);onReadCallback_(recvBuffer_);} else if (0 == recvNum) {onCloseCallback_();break;} else {onErrorCallback_(TCPCONN_ERROR_RECV);break;}}std::cout << "sendBufferThread exit" << std::endl;}Connector.cpp
#include "Connector.h"#include <Windows.h>Connector::Connector(const std::string &ip, unsigned short port): ip_(ip), port_(port), func_(NULL), sock_(INVALID_SOCKET), connected_(false){}Connector::~Connector(void){stop();}void Connector::start(){connect();}void Connector::stop(){connected_ = false;if (INVALID_SOCKET != sock_) {::shutdown(sock_, 2); // FIXME::closesocket(sock_);sock_ = INVALID_SOCKET;}}void Connector::connect(){sockaddr_in sin;memset(&sin, 0, sizeof(sin));sin.sin_family = AF_INET;sin.sin_addr.s_addr = inet_addr(ip_.c_str());sin.sin_port = htons(port_);sock_ = ::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);if (INVALID_SOCKET != sock_) {if (0 == ::connect(sock_, (SOCKADDR*)&sin, sizeof(sin))) {connected_ = true;} else {::closesocket(sock_);sock_ = INVALID_SOCKET;}}}
Thread.cpp
#include "Thread.h"#include <process.h>#include <assert.h>Thread::Thread(const ThreadFunc &func, const std::string &name): handle_(NULL), tid_(0), started_(false), func_(func), name_(name){}Thread::~Thread(){CloseHandle(handle_);}void Thread::start(){started_ = true;handle_ = (HANDLE)_beginthreadex(NULL, 0, startThread, this, 0, &tid_);assert(handle_ > 0);}int Thread::join(){if (GetCurrentThreadId() == tid_) {return 0;}return WaitForSingleObject(handle_, INFINITE);}unsigned int Thread::startThread(void *data){Thread *thread = static_cast<Thread*>(data);thread->runInThread();return 0;}void Thread::runInThread(){assert(GetCurrentThreadId() == tid_);if (func_) {func_();}started_ = false;}
WsaStartup.cpp
#include "WsaStartup.h"#include <Windows.h>#include <crtdbg.h>WsaStartup::WsaStartup(unsigned char majorVer, unsigned char minorVer){WSAData wsaData;_ASSERT(0 == WSAStartup(MAKEWORD(majorVer, minorVer), &wsaData));}WsaStartup::~WsaStartup(void){WSACleanup();}
0 0
- windows channel
- Channel
- channel
- channel
- Channel
- channel
- Channel
- Channel
- Channel 9上的两个新Windows 8 示例视频
- Channel 9: Windows Mobile平台上的.NET应用开发视频
- 新的Channel 9视频: 在Windows Azure上NewsGator总计3百万帖子/天
- Channel [v]
- channel bank
- Channel,Band
- struct channel
- NIO channel
- Channel Allocation
- Channel LA4789
- Ubuntu下配置samba服务器
- oracle安装
- 看来中国对知识产权的保护还是做得不够——腾迅你可能要无敌了
- opencv 浮点数取整 cvFloor cvRound cvCeil 比较
- Mac OS中如何显示和隐藏文件
- windows channel
- ubuntu中firefox浏览器中flash插件的安装
- 前端技术汇总
- Linux QT 环境搭建
- 工业4.0
- windows8开机出现start pxe over ipv4问题解决
- 视图控制器和视图类
- 嵌入式系统C语言编程小心使用局部变量
- python之单词统计(words count)