pans
2017-08-30 71c92f101b6c8b4a678a8c3cfe2d8edbf488efa4
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
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
#define UNIX_PLATFORM
#include "tcpComm.h"
 
tcpComm::tcpComm() :
        m_sockfd(0),m_nCommTimeOut(0), m_nRefreshMode(0), m_nTimeFailMode(0) {
}
 
tcpComm::~tcpComm() {
}
 
bool tcpComm::Create(long nCommTimeOut, long nRefreshMode, long nTimeFailMode) {
    if (nCommTimeOut < 0)
        return false;
 
    m_nCommTimeOut = nCommTimeOut;
    m_nRefreshMode = nRefreshMode;
    m_nTimeFailMode = nTimeFailMode;
 
    return true;
}
 
int tcpComm::CreateNetServer(unsigned short nServicePort) {
    //int sockfd;
    int optval = 1;
 
    struct sockaddr_in serv_addr;
    m_sockfd = socket(AF_INET, SOCK_STREAM, 0);
#ifdef UNIX_PLATFORM
    if (m_sockfd <= 0)
        return TCC_INVALIDVALUE;
#else
    if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET)
    return TCC_INVALIDVALUE;
#endif
 
    memset((char *) &serv_addr, 0, sizeof(serv_addr));
    serv_addr.sin_family = AF_INET;
    serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
    serv_addr.sin_port = htons(nServicePort);
 
    setsockopt(m_sockfd, SOL_SOCKET, SO_REUSEADDR, (const char*) &optval, sizeof(optval));
    //setsockopt(sockfd, SOL_SOCKET, SO_OOBINLINE, (const char*)&optval, sizeof(optval));
#ifdef UNIX_PLATFORM
    if (bind(m_sockfd, (struct sockaddr*) &serv_addr, sizeof(serv_addr))
            < 0)
#else
            if (bind(sockfd, (struct sockaddr*) &serv_addr, sizeof(serv_addr)) == SOCKET_ERROR)
#endif
            {
        TCP_CLOSE(m_sockfd);
        return TCC_INVALIDVALUE;
    }
#ifdef UNIX_PLATFORM
    if (listen(m_sockfd, 5) < 0)
#else
            if (listen(sockfd, 5) == SOCKET_ERROR)
#endif
            {
        TCP_CLOSE(m_sockfd);
        return TCC_INVALIDVALUE;
    }
 
    return (int) m_sockfd;
}
 
int tcpComm::WaitingNetServer() {
    int _sockfd;
    struct sockaddr_in cli_addr;
 
    socklen_t clilen = sizeof(cli_addr);
    memset(&cli_addr, 0, sizeof(cli_addr));
    _sockfd = accept(m_sockfd, (struct sockaddr*) &cli_addr, &clilen);
 
#ifdef UNIX_PLATFORM
    if (_sockfd < 0)
        return TCC_INVALIDVALUE;
#else
    if (_sockfd == INVALID_SOCKET)
    return TCC_INVALIDVALUE;
#endif
 
    return (int) _sockfd;
}
 
int tcpComm::ConnectNetServer(const char * pSerIp, unsigned short nSerPort) {
    //int sockfd;
    struct sockaddr_in serv_addr;
 
    memset((char*) &serv_addr, 0, sizeof(serv_addr));
 
    serv_addr.sin_family = AF_INET;
    serv_addr.sin_addr.s_addr = inet_addr(pSerIp);
    serv_addr.sin_port = htons(nSerPort);
 
#ifdef UNIX_PLATFORM
    if ((m_sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
#else
        if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET)
#endif
        return TCC_INVALIDVALUE;
 
#ifdef UNIX_PLATFORM
    if (connect(m_sockfd, (struct sockaddr*) &serv_addr, sizeof(serv_addr))
            < 0)
#else
            if (connect(sockfd, (struct sockaddr*) &serv_addr, sizeof(serv_addr)) == SOCKET_ERROR)
#endif
            {
        TCP_CLOSE(m_sockfd);
        return TCC_INVALIDVALUE;
    }
 
    return m_sockfd;
}
 
int tcpComm::EnableNoBlockMode(int flag) {
#ifdef UNIX_PLATFORM
    if (flag)
        return fcntl(m_sockfd, F_SETFL, fcntl(m_sockfd, F_GETFL, 0) | O_NDELAY);
    else
        return fcntl(m_sockfd, F_SETFL, fcntl(m_sockfd, F_GETFL, 0) & ~O_NDELAY);
#else
    u_long optval;
 
    if (flag)
    optval = 1;
    else
    optval = 0;
    return ioctlsocket(sockfd, FIONBIO, &optval);
#endif
}
 
int tcpComm::SendData(unsigned char *send_buf, long nSize) {
    unsigned char *p_buf;
    int byte_remain;
    int byte_write;
    long timecount; /* 时间记数值(以0.01秒为单位)*/
 
    if (send_buf == NULL)
        return 0;
    if ((m_sockfd <= 0) || (nSize <= 0) || (m_nCommTimeOut < 0))
        return 0;
 
    p_buf = send_buf; /* 记录初始指针 */
    byte_remain = (int) nSize; /* 记录期望的读数值 */
    byte_write = 0; /* 实际读数值 */
    timecount = 0; /* 初始化超时时间 */
    while ((timecount <= m_nCommTimeOut) && (byte_remain > 0)) {
#ifdef UNIX_PLATFORM
        switch (byte_write = write(m_sockfd, p_buf, byte_remain)) /* 发送数据 */
#else
        switch (byte_write = send(sockfd, (char*) p_buf, byte_remain, 0)) /* 发送数据 */
#endif
        {
            case SOCKET_ERROR:
#ifdef UNIX_PLATFORM
                if (errno == EWOULDBLOCK) /* 非阻塞方式 */
#else
                        if (WSAGetLastError() == WSAEWOULDBLOCK) /* 非阻塞方式 */
#endif
                        {
                    if (m_nCommTimeOut > 0)
                        TCP_DELAY(10); /* 如果要求延时 */
                    timecount++; /* 延时计数器加1 */
                    break;
                } else
                    return TCC_INVALIDVALUE; /* 其他错误(例如EINTR信号中断) */
 
            case 0:
                if (m_nCommTimeOut > 0)
                    TCP_DELAY(10); /* 如果要求延时 */
                timecount++; /* 延时计数器加1 */
                break;
 
            default:
                if (m_nRefreshMode)
                    timecount = 0; /* 重新记时 */
                byte_remain -= byte_write; /* 修改剩余的发送字节数 */
                p_buf += byte_write; /* 移动缓冲指针 */
                byte_write = 0; /* 重新记数发送的字节数 */
            }
        }
 
        if ((m_nTimeFailMode) && (timecount >= m_nCommTimeOut)) /* 超时断情况 */
            return TCC_INVALIDVALUE;
 
        return (nSize - byte_remain); /* 返回实际发送字节数 */
    }
 
    int tcpComm::SendFile(char *filename) {
        int byte_write;
        int byte_block;
        int byte_ret;
        int timeout_times;
 
        struct stat filestat;
        FILE* fp_data;
 
        unsigned char * m_pFileTransBuf;        // 文件传输块
        long m_nTransBlkSize = 2048;    // 文件传输块大小
 
        if (stat(filename, &filestat) != 0)
            return 0;
 
        byte_write = 0;
        timeout_times = 0;
 
        m_pFileTransBuf = new unsigned char[m_nTransBlkSize];
        if (m_pFileTransBuf == NULL)
            return -1;
 
        if ((fp_data = fopen(filename, "rb")) == NULL) {
            delete m_pFileTransBuf;
            return 0;
        }
 
        while ((byte_write < filestat.st_size) && (timeout_times < 3)) {
            byte_block = (int) (filestat.st_size - byte_write);
            if (byte_block > m_nTransBlkSize)
                byte_block = (int) m_nTransBlkSize;
 
            fseek(fp_data, byte_write, SEEK_SET);
            fread(m_pFileTransBuf, sizeof(char), byte_block, fp_data);
 
            byte_ret = SendData(m_pFileTransBuf, byte_block);
 
            if (byte_ret < 0)
                break;
            if (byte_ret == 0)
                timeout_times++;
            if (byte_ret > 0)
                timeout_times = 0;
 
            byte_write += byte_ret;
        }
        fclose(fp_data);
 
        delete m_pFileTransBuf;
 
        if (byte_ret < 0)
            return TCC_INVALIDVALUE;         // 通信出错
        if (timeout_times >= 3)
            return TCC_INVALIDVALUE;     // 通信出错
 
        if (byte_write != filestat.st_size)
            return 0;
        else
            return filestat.st_size;
    }
 
    int tcpComm::RecvData(unsigned char *recv_buf, long nSize) {
        unsigned char *p_buf;
        int byte_remain;
        int byte_read;
        long timecount; /* 时间记数值(以0.01秒为单位)*/
 
        if (recv_buf == NULL)
            return 0;
        if ((m_sockfd <= 0) || (nSize <= 0) || (m_nCommTimeOut < 0))
            return 0;
 
        p_buf = recv_buf; /* 记录初始指针 */
        byte_remain = (int) nSize; /* 记录期望的读数值 */
        byte_read = 0; /* 实际读数值 */
        timecount = 0; /* 计算超时时间 */
        while ((timecount <= m_nCommTimeOut) && (byte_remain > 0)) {
#ifdef UNIX_PLATFORM
            switch (byte_read = read(m_sockfd, p_buf, byte_remain)) /* 接收数据 */
#else
            switch (byte_read = recv(sockfd, (char *) p_buf, byte_remain, 0))
#endif
            {
                case SOCKET_ERROR:
#ifdef UNIX_PLATFORM
                    if (errno == EWOULDBLOCK) /* 非阻塞方式 */
#else
                            if (WSAGetLastError() == WSAEWOULDBLOCK) /* 非阻塞方式 */
#endif
                            {
                        if (m_nCommTimeOut > 0)
                            TCP_DELAY(10); /* 如果要求延时 */
                        timecount++; /* 延时计数器加1 */
                        break;
                    } else
                        return TCC_INVALIDVALUE; /* 其他错误(例如EINTR信号中断) */
 
                case 0:
                    return TCC_INVALIDVALUE; /* 网络中断 */
 
                default:
                    if (m_nRefreshMode)
                        timecount = 0; /* 重新记时 */
                    byte_remain -= byte_read; /* 修改剩余的读取字节数 */
                    p_buf += byte_read; /* 移动缓冲指针 */
                    byte_read = 0; /* 重新记数读到的字节数 */
                }
            }
 
            if ((m_nTimeFailMode) && (timecount >= m_nCommTimeOut)) /* 超时断情况 */
                return TCC_INVALIDVALUE;
 
            return (nSize - byte_remain);
        }
 
        int tcpComm::RecvFile(char *filename, long nSize) {
            int byte_read;
            int byte_block;
            int byte_ret;
            int timeout_times;
 
            FILE *fp_data;
 
            unsigned char * m_pFileTransBuf;        // 文件传输块
            long m_nTransBlkSize = 2048;    // 文件传输块大小
 
            if (nSize <= 0)
                return 0;
 
            byte_read = 0;
            timeout_times = 0;
 
            m_pFileTransBuf = new unsigned char[m_nTransBlkSize];
            if (m_pFileTransBuf == NULL)
                return -1;
 
            if ((fp_data = fopen(filename, "wb")) == NULL) {
                delete m_pFileTransBuf;
                return 0;
            }
            while ((byte_read < nSize) && (timeout_times < 3)) {
                byte_block = (int) (nSize - byte_read);
                if (byte_block > m_nTransBlkSize)
                    byte_block = (int) m_nTransBlkSize;
 
                byte_ret = RecvData(m_pFileTransBuf, byte_block);
 
                if (byte_ret < 0)
                    break;
                if (byte_ret == 0)
                    timeout_times++;
                if (byte_ret > 0) {
                    fwrite(m_pFileTransBuf, sizeof(char), byte_ret, fp_data);
                    timeout_times = 0;
                }
 
                byte_read += byte_ret;
            }
            fclose(fp_data);
 
            delete m_pFileTransBuf;
 
            if (byte_ret < 0)
                return TCC_INVALIDVALUE;        // 通信出错
            if (timeout_times >= 3)
                return TCC_INVALIDVALUE;    // 通信出错
 
            if (byte_read != nSize)
                return 0;
            return nSize;
        }
 
        int tcpComm::CloseComm() {
            int iRet = -1;
            if (m_sockfd <= 0)
                return 0;
#ifdef UNIX_PLATFORM
            iRet = shutdown(m_sockfd, SHUT_RDWR);
#else
            iRet = shutdown(sockfd, SD_BOTH);
#endif
            if (0 == iRet) {
                return TCP_CLOSE(m_sockfd);
            } else
                return iRet;
 
        }