source: libcf/trunk/src/cf_socket.c@ 35

Last change on this file since 35 was 35, checked in by cheese, 11 years ago

#1 separate example code and doxygen comment and fix logging push logic by vfire

File size: 7.2 KB
Line 
1/**
2 * @file cf_socket.c
3 * @author myusgun <myusgun@gmail.com>
4 * @version 0.1
5 */
6#include "cf_socket.h"
7#include "cf_local.h"
8
9#ifdef _WIN32
10# pragma comment (lib, "ws2_32.lib")
11# define close(__sock) closesocket(__sock)
12# define sa_family_t unsigned short
13#else
14#endif
15
16#include <string.h>
17
18#define CHECK_SOCKET_INIT() \
19 if (!CF_Socket_IsInitialized ()) \
20 return CF_ERROR_SOCKET_NOT_INITIALIZED
21
22#define CHECK_INVALID_SOCKET(__sock) \
23 if (__sock < 0) \
24 return CF_ERROR_SOCKET_INVALID_SOCKET
25
26static CF_BOOL gInitialized = CF_FALSE;
27
28/**
29 * 소켓의 초기화 상태 확인
30 *
31 * @return 초기화 된 경우, CF_TRUE; 그렇지 않은 경우, CF_FALSE
32 */
33CF_BOOL
34CF_Socket_IsInitialized (void)
35{
36 return gInitialized;
37}
38
39/**
40 * 소켓 초기화
41 *
42 * @return 성공 시, CF_OK; 실패 시, 오류 코드
43 */
44int
45CF_Socket_Initialize (void)
46{
47 int result = 0;
48
49#ifdef WIN32
50 WSADATA winsockData;
51 result = WSAStartup (MAKEWORD (2, 0), &winsockData);
52#endif
53 gInitialized = CF_TRUE;
54
55 if (result != 0)
56 return CF_ERROR_SOCKET_INITIALIZE;
57
58 return CF_OK;
59}
60
61/**
62 * 소켓 해제
63 *
64 * @return 성공 시, CF_OK; 실패 시, 오류 코드
65 */
66int
67CF_Socket_Finalize (void)
68{
69 int result = 0;
70
71 CHECK_SOCKET_INIT ();
72
73#ifdef WIN32
74 result = WSACleanup ();
75#endif
76 if (result != 0)
77 return CF_ERROR_SOCKET_FINALIZE;
78
79 return CF_OK;
80}
81
82/**
83 * 소켓 닫기
84 *
85 * @return 성공 시, CF_OK; 실패 시, 오류 코드
86 *
87 * @param sock 소켓
88 */
89int
90CF_Socket_Close (const int sock)
91{
92 int result = 0;
93
94 CHECK_INVALID_SOCKET (sock);
95
96 result = close (sock);
97
98 if (result != 0)
99 return CF_ERROR_SOCKET_CLOSE;
100
101 return CF_OK;
102}
103
104/**
105 * 소켓 옵션 설정
106 *
107 * @return 성공 시 CF_OK; 실패 시, 오류 코드
108 *
109 * @param sock 소켓
110 * @param optname 옵션 이름
111 * @param optval 설정할 옵션 값의 메모리
112 * @param optlen 설정할 옵션의 길이
113 */
114int
115CF_Socket_SetOption (const int sock,
116 const int optname,
117 const void * optval,
118 const size_t optlen)
119{
120 int result = 0;
121
122 CHECK_INVALID_SOCKET (sock);
123
124 result = setsockopt (sock,
125 SOL_SOCKET,
126 optname,
127#ifdef _WIN32
128 (char *) optval,
129#else
130 optval,
131#endif
132 (socklen_t) optlen);
133 if (result < 0)
134 return CF_ERROR_SOCKET_SET_OPTION;
135
136 return CF_OK;
137}
138
139/**
140 * 소켓 옵션 얻기
141 *
142 * @return 성공 시 CF_OK; 실패 시, 오류 코드
143 *
144 * @param sock 소켓
145 * @param optname 옵션 이름
146 * @param optval 옵션 값을 가져올 메모리
147 * @param optlen 옵션 길이를 가져올 메모리
148 */
149int
150CF_Socket_GetOption (const int sock,
151 const int optname,
152 void * optval,
153 size_t * optlen)
154{
155 int result = 0;
156
157 CHECK_INVALID_SOCKET (sock);
158
159 result = getsockopt (sock,
160 SOL_SOCKET,
161 optname,
162#ifdef _WIN32
163 (char *) optval,
164#else
165 optval,
166#endif
167 (socklen_t *) optlen);
168 if (result < 0)
169 return CF_ERROR_SOCKET_GET_OPTION;
170
171 return CF_OK;
172}
173
174/**
175 * 소켓에 타임아웃 설정
176 *
177 * @return 성공 시 CF_OK; 실패 시, 오류 코드
178 *
179 * @param sock 소켓
180 * @param timeout 타임아웃(sec)
181 */
182int
183CF_Socket_SetTimeout (const int sock,
184 const int timeout)
185{
186 int result = 0;
187
188#ifdef _WIN32
189 int time_ms = timeout * 1000;
190#else
191 struct timeval timeval;
192 timeval.tv_sec = timeout;
193 timeval.tv_usec= 0;
194#endif
195
196 CHECK_INVALID_SOCKET (sock);
197
198 if (timeout < 0)
199 return CF_ERROR_SOCKET_INVALID_ARGS;
200
201 result = CF_Socket_SetOption (sock,
202 SO_RCVTIMEO,
203#ifdef _WIN32
204 &time_ms,
205 sizeof (time_ms));
206#else
207 &timeval,
208 sizeof (timeval));
209#endif
210 if (result < 0)
211 return CF_ERROR_SOCKET_SET_TIMEOUT;
212
213 return CF_OK;
214}
215
216/**
217 * 소켓 연결
218 *
219 * @return 성공 시, 연결된 소켓; 실패 시, 오류 코드
220 *
221 * @param ip 연결할 호스트의 주소 (도메인 이름 가능)
222 * @param port 연결할 호스트의 포트번호
223 */
224int
225CF_Socket_Connect (const char * ip,
226 const unsigned short port)
227{
228 int result = 0;
229 int sock = 0;
230 struct sockaddr_in address;
231 struct hostent * hostEnt;
232
233 CHECK_SOCKET_INIT ();
234
235 sock = socket (PF_INET, SOCK_STREAM, IPPROTO_TCP);
236 if (sock < 0)
237 return CF_ERROR_SOCKET_CREATE;
238
239 address.sin_family = AF_INET;
240 address.sin_port = htons (port);
241 address.sin_addr.s_addr = inet_addr (ip);
242
243 TRY
244 {
245 if (address.sin_addr.s_addr == (unsigned int)-1)
246 {
247 hostEnt = gethostbyname (ip);
248 if (hostEnt == NULL)
249 {
250 result = CF_ERROR_SOCKET_GET_HOST;
251 TRY_BREAK;
252 }
253
254 address.sin_family = (sa_family_t) hostEnt->h_addrtype;
255 memcpy (&(address.sin_addr.s_addr), hostEnt->h_addr, (size_t) hostEnt->h_length);
256 }
257
258 result = connect (sock, (struct sockaddr *) &address, sizeof (address));
259 if (result < 0)
260 {
261 result = CF_ERROR_SOCKET_CONNECT;
262 TRY_BREAK;
263 }
264 }
265 CATCH_IF (result < 0)
266 {
267 CF_Socket_Close (sock);
268 return result;
269 }
270
271 return sock;
272}
273
274/**
275 * 서버 열기
276 *
277 * @return 성공 시, 서버 소켓; 실패 시, 오류 코드
278 *
279 * @param port 서버 포트
280 * @param backlog listen 시의 backlog 수
281 */
282int
283CF_Socket_Server (const unsigned short port,
284 const int backlog)
285{
286 int result = 0;
287 int sock = 0;
288 struct sockaddr_in address;
289
290 CHECK_SOCKET_INIT ();
291
292 sock = socket (PF_INET, SOCK_STREAM, IPPROTO_TCP);
293 if (sock < 0)
294 return CF_ERROR_SOCKET_CREATE;
295
296 address.sin_family = AF_INET;
297 address.sin_addr.s_addr = htonl (INADDR_ANY);
298 address.sin_port = htons (port);
299
300 TRY {
301 result = bind (sock, (struct sockaddr *) &address, sizeof (struct sockaddr));
302 if (result < 0)
303 {
304 result = CF_ERROR_SOCKET_BIND;
305 TRY_BREAK;
306 }
307
308 result = listen (sock, backlog);
309 if (result < 0)
310 {
311 result = CF_ERROR_SOCKET_LISTEN;
312 TRY_BREAK;
313 }
314 }
315 CATCH_IF (result < 0)
316 {
317 CF_Socket_Close (sock);
318 return result;
319 }
320
321 return sock;
322}
323
324/**
325 * 소켓 연결
326 *
327 * @return 성공 시, 연결된 소켓; 실패 시, 오류 코드
328 *
329 * @param sock 서버 소켓
330 * @param address [옵션] 클라이언트 정보를 담을 sockaddr_in 구조체 포인터
331 */
332int
333CF_Socket_Accept (const int sock,
334 struct sockaddr_in * address)
335{
336 int sockClient;
337 struct sockaddr_in remoteAddress;
338 socklen_t len = sizeof (remoteAddress);
339
340 CHECK_INVALID_SOCKET (sock);
341
342 sockClient = accept (sock, (struct sockaddr *) &remoteAddress, &len);
343 if (sockClient < 0)
344 return CF_ERROR_SOCKET_ACCEPT;
345
346 if (address != NULL)
347 memcpy ((void *) address, (void *) &remoteAddress, sizeof (struct sockaddr_in));
348
349 return sockClient;
350}
351
352/**
353 * 데이터 송신
354 *
355 * @return 성공 시, CF_OK; 실패 시, 오류 코드
356 *
357 * @param sock 소켓
358 * @param buf 송신할 데이터
359 * @param len 송신할 데이터의 길이
360 */
361int
362CF_Socket_Send (const int sock,
363 const void * buf,
364 const int len)
365{
366 int result = 0;
367
368 CHECK_INVALID_SOCKET (sock);
369
370 result = (int) send (sock, buf, (size_t) len, 0);
371 if (result != len)
372 return CF_ERROR_SOCKET_SEND;
373
374 return CF_OK;
375}
376
377/**
378 * 데이터 수신
379 *
380 * @return 성공 시, 수신한 데이터의 길이; 실패 시, 오류 코드
381 *
382 * @param sock 소켓
383 * @param buf 데이터를 수신할 버퍼
384 * @param len 데이터를 수신할 버퍼의 최대 크기
385 */
386int
387CF_Socket_Recv (const int sock,
388 void * buf,
389 const int len)
390{
391 int result = 0;
392
393 CHECK_INVALID_SOCKET (sock);
394
395 result = (int) recv (sock, buf, (size_t) len, 0);
396 if (result < 0)
397 return CF_ERROR_SOCKET_RECV;
398
399 return result;
400}
Note: See TracBrowser for help on using the repository browser.