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

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

#1 change interface of log from context to id-number

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