其中使用到的其他头文件地址:
线程:http://blog.youkuaiyun.com/tujiaw/article/details/8795014
阻塞队列:http://blog.youkuaiyun.com/tujiaw/article/details/8779466
消息:http://blog.youkuaiyun.com/tujiaw/article/details/8665610
#define DISALLOW_COPY_AND_ASSIGN(ClassName) \
private: \
ClassName(const ClassName&); \
ClassName& operator= (const ClassName&)
#include <WinSock2.h>
#include <assert.h>
#include <string>
#include <memory>
#include "Def.h"
#include "Thread.h"
#include "Message.h"
#include "BlockQueue.h"
#pragma comment(lib, "Ws2_32.lib")
class WsaGuard
{
public:
WsaGuard() { int iret = WSAStartup(MAKEWORD(2, 2), &wsaData_); assert(0 == iret); }
~WsaGuard() { WSACleanup(); }
private:
WSADATA wsaData_;
};
typedef std::tr1::function<void(MessagePtr&)> MessageCallback;
class TcpClient
{
DISALLOW_COPY_AND_ASSIGN(TcpClient);
public:
TcpClient(const std::string& ip, unsigned short port);
~TcpClient();
void setSendCallback(const MessageCallback& func) { sendCallback = func; }
void setRecvCallback(const MessageCallback& func) { recvCallback_ = func; }
int start();
void sendMessage(MessagePtr& msgPtr);
private:
void sendLoop();
void recvLoop();
private:
WsaGuard *init_;
SOCKET sock_;
std::string ip_;
unsigned short port_;
typedef std::tr1::shared_ptr<Thread> ThreadPtr;
ThreadPtr sendPtr_;
ThreadPtr recvPtr_;
MessageCallback sendCallback;
MessageCallback recvCallback_;
BlockQueue<MessagePtr> sendQueue_;
};
#include "stdafx.h"
#include "Net.h"
#include <sstream>
TcpClient::TcpClient(const std::string& ip, unsigned short port)
: init_(NULL), sock_(INVALID_SOCKET), ip_(ip), port_(port)
{
init_ = new WsaGuard();
}
TcpClient::~TcpClient()
{
closesocket(sock_);
if (init_) { delete init_; }
}
int TcpClient::start()
{
sock_ = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (INVALID_SOCKET == sock_)
{
return RET_CREATE_SOCKET;
}
SOCKADDR_IN sin;
sin.sin_family = AF_INET;
sin.sin_port = htons(port_);
sin.sin_addr.S_un.S_addr = inet_addr(ip_.c_str());
int iconn = connect(sock_, (SOCKADDR*)&sin, sizeof(sin));
if (SOCKET_ERROR == iconn)
{
closesocket(sock_);
return RET_CONNECT_SERVER;
}
sendPtr_.reset(new Thread(std::tr1::bind(&TcpClient::sendLoop, this), "send"));
sendPtr_->start();
recvPtr_.reset(new Thread(std::tr1::bind(&TcpClient::recvLoop, this), "recv"));
recvPtr_->start();
return RET_SUCCESS;
}
void TcpClient::sendMessage(MessagePtr& msg) // FIXME
{
OutputDebugStringA("send message");
sendQueue_.put(msg);
}
void TcpClient::sendLoop()
{
while (1)
{
OutputDebugStringA("111");
MessagePtr msgPtr = sendQueue_.take();
int isend = send(sock_, (char*)msgPtr->get(), msgPtr->count(), 0);
if (SOCKET_ERROR == isend)
{
return;
}
}
}
void TcpClient::recvLoop()
{
const int bufferLen = 4096;
char buffer[bufferLen];
while (1)
{
memset(buffer, 0, bufferLen);
int irecv = recv(sock_, buffer, bufferLen, 0);
if (SOCKET_ERROR == irecv)
{
return;
}
MessagePtr msgPtr(new Message((unsigned char*)buffer, irecv));
recvCallback_(msgPtr);
}
}
// 使用片段
typedef std::tr1::shared_ptr<TcpClient> TcpClientPtr;
TcpClientPtr m_clientPtr;
// ...
m_clientPtr.reset(new TcpClient(GetIp().c_str(), GetPort()));
m_clientPtr->setRecvCallback(std::tr1::bind(&CSpendDlg::OnMessage, this, std::tr1::placeholders::_1));
int iret = m_clientPtr->start();
// ...
m_clientPtr->sendMessage(msg);