-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathODSocket.cpp
More file actions
276 lines (243 loc) · 5.26 KB
/
ODSocket.cpp
File metadata and controls
276 lines (243 loc) · 5.26 KB
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
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
#include "ODSocket.h"
#include <stdio.h>
#ifdef WIN32
#pragma comment(lib, "wsock32")
#endif
ODSocket::ODSocket(SOCKET sock)
{
m_sock = sock;
}
ODSocket::~ODSocket()
{
}
int ODSocket::Init()
{
#ifdef WIN32
/*
http://msdn.microsoft.com/zh-cn/vstudio/ms741563(en-us,VS.85).aspx
typedef struct WSAData {
WORD wVersion; //winsock version
WORD wHighVersion; //The highest version of the Windows Sockets specification that the Ws2_32.dll can support
char szDescription[WSADESCRIPTION_LEN+1];
char szSystemStatus[WSASYSSTATUS_LEN+1];
unsigned short iMaxSockets;
unsigned short iMaxUdpDg;
char FAR * lpVendorInfo;
}WSADATA, *LPWSADATA;
*/
WSADATA wsaData;
//#define MAKEWORD(a,b) ((WORD) (((BYTE) (a)) | ((WORD) ((BYTE) (b))) << 8))
WORD version = MAKEWORD(2, 0);
int ret = WSAStartup(version, &wsaData);//win sock start up
if ( ret )
{
return -1;
}
#endif
return 0;
}
//this is just for windows
int ODSocket::Clean()
{
#ifdef WIN32
return (WSACleanup());
#endif
return 0;
}
ODSocket& ODSocket::operator = (SOCKET s)
{
m_sock = s;
return (*this);
}
ODSocket::operator SOCKET ()
{
return m_sock;
}
//create a socket object win/lin is the same
// af:
bool ODSocket::Create(int af, int type, int protocol)
{
m_sock = socket(af, type, protocol);
if ( m_sock == INVALID_SOCKET ) {
return false;
}
return true;
}
/*
1.建立socket
2.将该socket设置为非阻塞模式
3.调用connect()
4.使用select()检查该socket描述符是否可写(注意,是可写)
5.根据select()返回的结果判断connect()结果
6.将socket设置为阻塞模式(如果你的程序不需要用阻塞模式的,这步就省了,不过一般情况下都是用阻塞模式的,这样也容易管理)
*/
bool ODSocket::Connect(const char* ip, unsigned short port, int timeOut)
{
struct sockaddr_in svraddr;
struct hostent *pHost;
svraddr.sin_family = AF_INET;
svraddr.sin_addr.s_addr = inet_addr(ip);
svraddr.sin_port = htons(port);
if(svraddr.sin_addr.s_addr == INADDR_NONE)
{
//如果输入的是域名
pHost = (struct hostent*)gethostbyname(ip);
if(pHost==NULL)
{
printf("Init socket s_addr error!");
return false;
}
svraddr.sin_addr.s_addr =((struct in_addr*)pHost->h_addr)->s_addr;
}
unsigned long ul = 1;
#ifdef _WIN32
ioctlsocket(m_sock, FIONBIO, &ul); //设置为非阻塞模式
#else
ioctl(m_sock, FIONBIO, &ul); //设置为非阻塞模式
#endif
int error = -1;
int len = sizeof(int);
timeval tm;
fd_set set;
bool ret = false;
if(connect(m_sock, (struct sockaddr *)&svraddr, sizeof(svraddr)) == -1)
{
#ifdef _WIN32
#else
if (errno != EINPROGRESS)
{
return false;
}
#endif
tm.tv_sec = timeOut;
tm.tv_usec = 0;
FD_ZERO(&set);
FD_SET(m_sock, &set);
if( select(m_sock+1, NULL, &set, NULL, &tm) > 0)
{
getsockopt(m_sock, SOL_SOCKET, SO_ERROR, (char *)&error, (socklen_t *)&len);
if(error == 0)
ret = true;
else
ret = false;
}
else
ret = false;
}
else
ret = true;
ul = 0;
#ifdef _WIN32
//ioctlsocket(m_sock, FIONBIO, &ul); //设置为阻塞模式
#else
//ioctl(m_sock, FIONBIO, &ul); //设置为阻塞模式
#endif
return ret;
}
bool ODSocket::Bind(unsigned short port)
{
struct sockaddr_in svraddr;
svraddr.sin_family = AF_INET;
svraddr.sin_addr.s_addr = INADDR_ANY;
svraddr.sin_port = htons(port);
int opt = 1;
if ( setsockopt(m_sock, SOL_SOCKET, SO_REUSEADDR, (char*)&opt, sizeof(opt)) < 0 )
return false;
int ret = bind(m_sock, (struct sockaddr*)&svraddr, sizeof(svraddr));
if ( ret == SOCKET_ERROR ) {
return false;
}
return true;
}
//for server
bool ODSocket::Listen(int backlog)
{
int ret = listen(m_sock, backlog);
if ( ret == SOCKET_ERROR ) {
return false;
}
return true;
}
bool ODSocket::Accept(ODSocket& s, char* fromip)
{
struct sockaddr_in cliaddr;
socklen_t addrlen = sizeof(cliaddr);
SOCKET sock = accept(m_sock, (struct sockaddr*)&cliaddr, &addrlen);
if ( sock == SOCKET_ERROR ) {
return false;
}
s = sock;
if ( fromip != NULL )
sprintf(fromip, "%s", inet_ntoa(cliaddr.sin_addr));
return true;
}
int ODSocket::Send(const char* buf, int len, int flags)
{
if (m_sock < 0)
{
return 0;
}
int bytes;
int count = 0;
while ( count < len ) {
bytes = send(m_sock, buf + count, len - count, flags);
if ( bytes == -1 || bytes == 0 )
return -1;
count += bytes;
}
return count;
}
int ODSocket::Recv(char* buf, int len, int flags)
{
if (m_sock < 0)
{
return 0;
}
fd_set read;
timeval tm;
FD_ZERO(&read);
FD_SET(m_sock, &read);
tm.tv_sec=0;
tm.tv_usec=0;
select(m_sock+1, &read, NULL, NULL, &tm);
if(FD_ISSET(m_sock,&read))
{
int ret = recv(m_sock, buf, len, flags);
if (ret<=0)
{
return -1;
}
return ret;
}
return 0;
}
int ODSocket::Close()
{
m_sock = -1;
#ifdef WIN32
return (closesocket(m_sock));
#else
return (close(m_sock));
#endif
}
int ODSocket::GetError()
{
#ifdef WIN32
return (WSAGetLastError());
#else
return (errno);
#endif
}
bool ODSocket::DnsParse(const char* domain, char* ip)
{
struct hostent* p;
if ( (p = gethostbyname(domain)) == NULL )
return false;
sprintf(ip,
"%u.%u.%u.%u",
(unsigned char)p->h_addr_list[0][0],
(unsigned char)p->h_addr_list[0][1],
(unsigned char)p->h_addr_list[0][2],
(unsigned char)p->h_addr_list[0][3]);
return true;
}