-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathtcpserver.h
182 lines (160 loc) · 4.61 KB
/
tcpserver.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
#ifndef _D_TCPSERVER_H_
#define _D_TCPSERVER_H_
#include "iserver.h"
#include "outputbuffer.h"
#include "sighandle.h"
#include <ev++.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <sys/socket.h>
#include <pthread.h>
#include <resolv.h>
#include <errno.h>
#include <queue>
#include <map>
#include <tr1/memory>
#include <tr1/functional>
#define SOCKET_CHANNEL_NUM 256
#define TCP_CONNECTION_TIMEOUT 600
class CTcpServer;
class CTcpConnection
{
public:
typedef std::tr1::shared_ptr<CTcpConnection> Pointer;
public:
CTcpConnection(CTcpServer * pTcpServer, const SocketClientData_t & sClient);
virtual ~CTcpConnection();
public:
void Send(COutputBuffer::Pointer pOutputBuffer);
void Close();
private:
void __IoCallback(ev::io &watcher, int revents);
void __TimerCallback(ev::timer &watcher, int revents);
void __ErrorCallback();
private:
SocketClientData_t m_SocketClient;
int m_Socket;
CTcpServer * m_pTcpServer;
ev::io m_Io;
ev::timer m_Timer;
std::queue<COutputBuffer::Pointer> m_WriteQueue;
int m_nLasttime;
};
class CSocketInfoChannel
{
typedef CTcpConnection::Pointer ConnectionPtr_t;
typedef std::map<SocketClientData_t, ConnectionPtr_t> ConnectionPtrMap_t;
public:
CSocketInfoChannel()
{
pthread_spin_init(&m_Spinlock, 0);
}
~CSocketInfoChannel()
{
pthread_spin_destroy(&m_Spinlock);
}
public:
void Add(const SocketClientData_t & sClient, const ConnectionPtr_t pConn)
{
pthread_spin_lock(&m_Spinlock);
m_Connections[sClient] = pConn;
pthread_spin_unlock(&m_Spinlock);
}
ConnectionPtr_t Get(const SocketClientData_t & sClient)
{
pthread_spin_lock(&m_Spinlock);
ConnectionPtr_t pConn;
ConnectionPtrMap_t::const_iterator it_find = m_Connections.find(sClient);
if (it_find != m_Connections.end())
{
pConn = it_find->second;
}
pthread_spin_unlock(&m_Spinlock);
return pConn;
}
void Remove(const SocketClientData_t & sClient)
{
pthread_spin_lock(&m_Spinlock);
m_Connections.erase(sClient);
pthread_spin_unlock(&m_Spinlock);
}
private:
ConnectionPtrMap_t m_Connections;
pthread_spinlock_t m_Spinlock;
};
class CSocketInfoManager
{
typedef CTcpConnection::Pointer ConnectionPtr_t;
public:
CSocketInfoManager(){}
~CSocketInfoManager(){}
public:
void Add(const SocketClientData_t & sClient, const ConnectionPtr_t pConn)
{
m_Channels[__Hash(sClient)].Add(sClient, pConn);
}
ConnectionPtr_t Get(const SocketClientData_t & sClient)
{
return m_Channels[__Hash(sClient)].Get(sClient);
}
void Remove(const SocketClientData_t & sClient)
{
m_Channels[__Hash(sClient)].Remove(sClient);
}
private:
int __Hash(const SocketClientData_t & sClient) const
{
return (sClient.Socket%SOCKET_CHANNEL_NUM);
}
private:
CSocketInfoChannel m_Channels[SOCKET_CHANNEL_NUM];
};
class CTcpServer: public ITcpServer
{
typedef std::tr1::function<void()> Function_t;
typedef std::vector<Function_t> FunctionList_t;
public:
CTcpServer(): m_nTimeout(TCP_CONNECTION_TIMEOUT)
{
pthread_spin_init(&m_Spinlock, 0);
}
virtual ~CTcpServer()
{
pthread_spin_destroy(&m_Spinlock);
}
public:
virtual void SetDataHandle(ITcpServerDataHandle * pDataHandle) { m_pDataHandle = pDataHandle; }
virtual bool Start(unsigned int IP, unsigned short Port);
virtual bool Stop();
virtual bool Send(SocketClientData_t sClient, const char *pData, int nDataLen);
virtual bool CloseClient(SocketClientData_t sClient);
public:
virtual void SetConnectionTimeout(int nTimeout) { m_nTimeout = nTimeout; }
virtual int GetConnectionTimeout() const { return m_nTimeout; }
public:
virtual void OnClientDisconnected(SocketClientData_t sClient, int nErrorCode);
virtual void OnClientDataReceived(SocketClientData_t sClient, const char * pData, int nDataLen);
virtual void OnClientRecvError(SocketClientData_t sClient, int nErrorCode);
virtual void OnClientSendError(SocketClientData_t sClient, int nErrorCode);
virtual void OnClientTimeout(SocketClientData_t sClient);
ev::dynamic_loop & GetLoop() { return m_Loop; }
protected:
bool __Send(SocketClientData_t sClient, COutputBuffer::Pointer pOutputBuffer);
void __Accept(ev::io &watcher, int revents);
void __AsyncCallback(ev::async &watcher, int revents);
protected:
CSocketInfoManager m_SocketInfoManager;
ITcpServerDataHandle * m_pDataHandle;
int m_nTimeout;
int m_Socket;
ev::dynamic_loop m_Loop;
ev::io m_ListenIo;
ev::async m_Async;
FunctionList_t m_Functions;
pthread_spinlock_t m_Spinlock;
};
#endif