Index: trunk/include/cf_error.h
===================================================================
--- trunk/include/cf_error.h	(revision 45)
+++ trunk/include/cf_error.h	(revision 46)
@@ -7,5 +7,5 @@
 #define CF_ERROR_BASE						CF_ERROR * 1000
 
-/* socket {{{ */
+/* file {{{ */
 #define CF_ERROR_FILE						CF_ERROR_BASE * 2
 /*------------------------------------------------------------*/
@@ -19,5 +19,5 @@
 #define CF_ERROR_FILE_MAKE_DIRECTORY		CF_ERROR_FILE - 8
 
-/* }}} socket */
+/* }}} file */
 
 /* socket {{{ */
@@ -32,5 +32,5 @@
 #define CF_ERROR_SOCKET_SET_OPTION			CF_ERROR_SOCKET - 7
 #define CF_ERROR_SOCKET_GET_OPTION			CF_ERROR_SOCKET - 8
-#define CF_ERROR_SOCKET_SET_TIMEOUT			CF_ERROR_SOCKET - 9
+#define CF_ERROR_SOCKET_TIMEOUT				CF_ERROR_SOCKET - 9
 #define CF_ERROR_SOCKET_INVALID_ARGS		CF_ERROR_SOCKET - 10
 #define CF_ERROR_SOCKET_INVALID_SOCKET		CF_ERROR_SOCKET - 11
@@ -41,4 +41,5 @@
 #define CF_ERROR_SOCKET_SEND				CF_ERROR_SOCKET - 16
 #define CF_ERROR_SOCKET_RECV				CF_ERROR_SOCKET - 17
+#define CF_ERROR_SOCKET_INTERNAL			CF_ERROR_SOCKET - 18
 /* }}} socket */
 
Index: trunk/include/cf_socket.h
===================================================================
--- trunk/include/cf_socket.h	(revision 45)
+++ trunk/include/cf_socket.h	(revision 46)
@@ -13,19 +13,15 @@
 
 #include "cf_base.h"
+
 #include <stddef.h>
 
-#ifdef _WIN32
-# include <WinSock2.h>
-#else
-# include <netinet/in.h>
-# include <sys/socket.h>
-# include <arpa/inet.h>
-# include <netdb.h>
-# include <unistd.h>
-#endif
+/** 타임아웃을 설정하지 않음 */
+#define CF_SOCKET_NO_TIMEOUT		-1
 
-#ifdef _WIN32
-typedef int socklen_t;
-#endif // #ifdef _WIN32
+/** 호스트 정보 */
+typedef struct cf_socket_hostinfo {
+	char			address[128];	/**< 원격 호스트 주소 */
+	unsigned short	port;			/**< 원격 호스트 포트 */
+} CF_Socket_HostInfo;
 
 #ifdef __cplusplus
@@ -34,52 +30,65 @@
 
 CF_EXPORT CF_BOOL
-CF_Socket_IsInitialized	(void);
+CF_Socket_IsInitialized		(void);
 
 CF_EXPORT int
-CF_Socket_Initialize	(void);
+CF_Socket_Initialize		(void);
 
 CF_EXPORT int
-CF_Socket_Finalize		(void);
+CF_Socket_Finalize			(void);
 
 CF_EXPORT int
-CF_Socket_Close			(const int sock);
+CF_Socket_Close				(const int sock);
 
 CF_EXPORT int
-CF_Socket_SetOption		(const int		sock,
-						 const int		optname,
-						 const void		* optval,
-						 const size_t	optlen);
+CF_Socket_SetOption			(const int		sock,
+							 const int		optname,
+							 const void		* optval,
+							 const size_t	optlen);
 
 CF_EXPORT int
-CF_Socket_GetOption		(const int	sock,
-						 const int	optname,
-						 void		* optval,
-						 size_t		* optlen);
+CF_Socket_GetOption			(const int	sock,
+							 const int	optname,
+							 void		* optval,
+							 size_t		* optlen);
 
 CF_EXPORT int
-CF_Socket_SetTimeout	(const int	sock,
-						 const int	timeout);
+CF_Socket_Connect			(const char				* ip,
+							 const unsigned short	port);
 
 CF_EXPORT int
-CF_Socket_Connect		(const char				* ip,
-						 const unsigned short	port);
+CF_Socket_ConnectTimeout	(const char				* ip,
+							 const unsigned short	port,
+							 const int				timeout);
 
 CF_EXPORT int
-CF_Socket_Server		(const unsigned short	port,
-						 const int				backlog);
+CF_Socket_Server			(const unsigned short	port,
+							 const int				backlog);
 
 CF_EXPORT int
-CF_Socket_Accept		(const int			sock,
-						 struct sockaddr_in	* address);
+CF_Socket_Accept			(const int			sock,
+							 CF_Socket_HostInfo	* host);
 
 CF_EXPORT int
-CF_Socket_Send			(const int	sock,
-						 const void	* buf,
-						 const int	len);
+CF_Socket_Send				(const int	sock,
+							 const void	* buf,
+							 const int	len);
 
 CF_EXPORT int
-CF_Socket_Recv			(const int	sock,
-						 void		* buf,
-						 const int	len);
+CF_Socket_SendTimeout		(const int	sock,
+							 const void	* buf,
+							 const int	len,
+							 const int	timeout);
+
+CF_EXPORT int
+CF_Socket_Recv				(const int	sock,
+							 void		* buf,
+							 const int	len);
+
+CF_EXPORT int
+CF_Socket_RecvTimeout		(const int	sock,
+							 void		* buf,
+							 const int	len,
+							 const int	timeout);
 
 #ifdef __cplusplus
Index: trunk/src/cf_file.c
===================================================================
--- trunk/src/cf_file.c	(revision 45)
+++ trunk/src/cf_file.c	(revision 46)
@@ -188,5 +188,5 @@
 	char	* d = stepPath;
 
-	sprintf (fullPath, "%s%c", path, DELIMITER);
+	snprintf (fullPath, sizeof (fullPath) - 1, "%s%c", path, DELIMITER);
 
 	for (*d++ = *f++ ; *f ; *d++ = *f++)
Index: trunk/src/cf_log.c
===================================================================
--- trunk/src/cf_log.c	(revision 45)
+++ trunk/src/cf_log.c	(revision 46)
@@ -304,5 +304,5 @@
 
 	CF_Log_Local_GetTimeString (datetime);
-	sprintf (buffer, "[%s][%s] ", datetime, prefix);
+	snprintf (buffer, sizeof (buffer) - 1, "[%s][%s] ", datetime, prefix);
 	vsprintf (buffer + strlen (buffer), fmt, valist);
 
@@ -408,5 +408,5 @@
 			TRY_BREAK;
 		}
-		sprintf (context->path, "%s", path);
+		snprintf (context->path, sizeof (context->path) -1, "%s", path);
 
 		if (size > 0)
Index: trunk/src/cf_socket.c
===================================================================
--- trunk/src/cf_socket.c	(revision 45)
+++ trunk/src/cf_socket.c	(revision 46)
@@ -8,12 +8,24 @@
 #include "cf_error.h"
 
+#include <stdio.h>
+#include <string.h>
+
 #ifdef _WIN32
+/* for windows {{{ */
+# include <WinSock2.h>
 # pragma comment (lib, "ws2_32.lib")
-# define close(__sock)	closesocket(__sock)
-# define sa_family_t	unsigned short
+/* }}} for windows */
 #else
-#endif
-
-#include <string.h>
+/* for linux/unix {{{ */
+# include <netinet/in.h>
+# include <sys/socket.h>
+# include <arpa/inet.h>
+# include <netdb.h>
+# include <unistd.h>
+# include <sys/un.h>
+# include <fcntl.h>
+# include <errno.h>
+/* }}} for linux/unix */
+#endif
 
 #define CHECK_SOCKET_INIT()					\
@@ -25,5 +37,73 @@
 		return CF_ERROR_SOCKET_INVALID_SOCKET
 
+#ifdef WIN32
+typedef int					socklen_t;
+# define sa_family_t		unsigned short
+# define close(__sock)		closesocket(__sock)
+# define CHECK_SELECT(x)	((x) == SOCKET_ERROR)
+# define GET_SYSTEM_ERROR()	WSAGetLastError ()
+# define ERROR_INTR			WSAEINTR
+#else
+# define CHECK_SELECT(x)	((x) < 0)
+# define GET_SYSTEM_ERROR()	errno
+# define ERROR_INTR			EINTR
+#endif
+
 static CF_BOOL gInitialized = CF_FALSE;
+
+static void
+CF_Socket_Local_SetNonBlocking (const int	sock,
+								CF_BOOL		boolean)
+{
+#ifdef WIN32
+	unsigned long mode = (boolean == CF_TRUE) ? 1 : 0;
+	ioctlsocket (sock, FIONBIO, &mode);
+#else
+	int flags = fcntl (sock, F_GETFL, 0);
+
+	if (boolean)
+		flags |=  O_NONBLOCK;
+	else
+		flags &= ~O_NONBLOCK;
+
+	fcntl (sock, F_SETFL, flags);
+#endif
+}
+
+static int
+CF_Socket_Local_CheckTimeout (const int	sock,
+							  const int	timeout)
+{
+	int				result = 0;
+	fd_set			readfds;
+	struct timeval	tv;
+	int				error;
+
+	if (!(timeout > CF_SOCKET_NO_TIMEOUT))
+		return CF_OK;
+
+	tv.tv_sec = timeout;
+	tv.tv_usec = 0;
+
+	FD_ZERO (&readfds);
+	FD_SET (sock, &readfds);
+
+	while (CHECK_SELECT (result = select (sock + 1, &readfds, NULL, NULL, &tv)))
+	{
+		error = GET_SYSTEM_ERROR ();
+		if (error != ERROR_INTR)
+		{
+			result = CF_ERROR_SOCKET_TIMEOUT;
+			return result;
+		}
+	}
+
+	if (FD_ISSET (sock, &readfds) == 0)
+	{
+		return CF_ERROR_SOCKET_INTERNAL;
+	}
+
+	return CF_OK;
+}
 
 /**
@@ -46,14 +126,10 @@
 CF_Socket_Initialize (void)
 {
-	int result = 0;
-
 #ifdef WIN32
 	WSADATA winsockData;
-	result = WSAStartup (MAKEWORD (2, 0), &winsockData);
+	if (WSAStartup (MAKEWORD (2, 0), &winsockData))
+	   return CF_ERROR_SOCKET_INITIALIZE;
 #endif
 	gInitialized = CF_TRUE;
-
-	if (result != 0)
-	   return CF_ERROR_SOCKET_INITIALIZE;
 	
 	return CF_OK;
@@ -68,13 +144,10 @@
 CF_Socket_Finalize (void)
 {
-	int result = 0;
-
 	CHECK_SOCKET_INIT ();
 
 #ifdef WIN32
-	result = WSACleanup ();
-#endif
-   	if (result != 0)
+   	if (WSACleanup ())
 	   return CF_ERROR_SOCKET_FINALIZE;
+#endif
 
 	return CF_OK;
@@ -174,56 +247,33 @@
 
 /**
- * 소켓에 타임아웃 설정
- *
- * @return 성공 시 CF_OK; 실패 시, 오류 코드
- *
- * @param sock		소켓
- * @param timeout	타임아웃(sec)
- */
-int
-CF_Socket_SetTimeout (const int	sock,
-					  const int timeout)
-{
-	int result = 0;
-
-#ifdef _WIN32
-	int time_ms = timeout * 1000;
-#else
-	struct timeval	timeval;
-	timeval.tv_sec = timeout;
-	timeval.tv_usec= 0;
-#endif
-
-	CHECK_INVALID_SOCKET (sock);
-
-	if (timeout < 0)
-		return CF_ERROR_SOCKET_INVALID_ARGS;
-
-	result = CF_Socket_SetOption (sock,
-								  SO_RCVTIMEO,
-#ifdef _WIN32
-								  &time_ms,
-								  sizeof (time_ms));
-#else
-								  &timeval,
-								  sizeof (timeval));
-#endif
-	if (result < 0)
-		return CF_ERROR_SOCKET_SET_TIMEOUT;
-
-	return CF_OK;
-}
-
-/**
  * 소켓 연결
  *
  * @return 성공 시, 연결된 소켓; 실패 시, 오류 코드
  *
- * @param ip	연결할 호스트의 주소 (도메인 이름 가능)
- * @param port	연결할 호스트의 포트번호
+ * @param ip		연결할 호스트의 주소 (도메인 이름 가능)
+ * @param port		연결할 호스트의 포트번호
  */
 int
 CF_Socket_Connect (const char			* ip,
 				   const unsigned short	port)
+{
+	return CF_Socket_ConnectTimeout (ip, port, CF_SOCKET_NO_TIMEOUT);
+}
+
+/**
+ * 타임아웃 동안 소켓 연결
+ *
+ * @return 성공 시, 연결된 소켓; 실패 시, 오류 코드
+ *
+ * @param ip		연결할 호스트의 주소 (도메인 이름 가능)
+ * @param port		연결할 호스트의 포트번호
+ * @param timeout	타임아웃 (초)
+ *
+ * @see CF_SOCKET_NO_TIMEOUT
+ */
+int
+CF_Socket_ConnectTimeout (const char			* ip,
+						  const unsigned short	port,
+						  const int				timeout)
 {
 	int					result = 0;
@@ -231,17 +281,30 @@
 	struct sockaddr_in	address;
 	struct hostent		* hostEnt;
+	struct linger		linger;
+
+	int					retval = 0;
+	size_t				length = 0;
+	struct timeval		tv;
+	fd_set				readfds;
+	fd_set				writefds;
 
 	CHECK_SOCKET_INIT ();
 
+	/* 1. create socket */
 	sock = socket (PF_INET, SOCK_STREAM, IPPROTO_TCP);
 	if (sock < 0)
 		return CF_ERROR_SOCKET_CREATE;
 
+	/* 2. set data */
 	address.sin_family		= AF_INET;
 	address.sin_port		= htons (port);
 	address.sin_addr.s_addr	= inet_addr (ip);
 
+	linger.l_onoff = 1;
+	linger.l_linger = 0;
+
 	TRY
 	{
+		/* 3. get ip from hostname if inet_addr() is failed */
 		if (address.sin_addr.s_addr == (unsigned int)-1)
 		{
@@ -254,9 +317,67 @@
 
 			address.sin_family = (sa_family_t) hostEnt->h_addrtype;
-			memcpy (&(address.sin_addr.s_addr), hostEnt->h_addr, (size_t) hostEnt->h_length);
-		}
-
+			memcpy (&(address.sin_addr.s_addr),
+					hostEnt->h_addr,
+					(size_t) hostEnt->h_length);
+		}
+
+		/* 4. set options */
+		result = CF_Socket_SetOption (sock, SO_LINGER, &linger, sizeof (linger));
+		if (result < 0)
+		{
+			result = CF_ERROR_SOCKET_SET_OPTION;
+			TRY_BREAK;
+		}
+
+		if (timeout > CF_SOCKET_NO_TIMEOUT)
+			CF_Socket_Local_SetNonBlocking (sock, CF_TRUE);
+
+		/* 5. connect */
 		result = connect (sock, (struct sockaddr *) &address, sizeof (address));
-		if (result < 0)
+		if (result == 0)
+		{
+			result = CF_OK;
+			TRY_BREAK;
+		}
+
+		/* 6. if connect() is returned, check timeout */
+		if (timeout == CF_SOCKET_NO_TIMEOUT)
+		{
+			result = CF_ERROR_SOCKET_TIMEOUT;
+			TRY_BREAK;
+		}
+
+		FD_ZERO (&readfds);
+		FD_SET ((unsigned int)sock, &readfds);
+		writefds = readfds;
+
+		tv.tv_sec = timeout;
+		tv.tv_usec = 0;
+
+		result = select (sock + 1, &readfds, &writefds, NULL, &tv);
+		if (result == 0)
+		{
+			result = CF_ERROR_SOCKET_TIMEOUT;
+			TRY_BREAK;
+		}
+
+		if (FD_ISSET (sock, &readfds) || FD_ISSET (sock, &writefds))
+		{
+			length = sizeof (retval);
+			retval = 0;
+
+			result = CF_Socket_GetOption (sock, SO_ERROR, &retval, &length);
+			if (result < 0)
+			{
+				result = CF_ERROR_SOCKET_GET_OPTION;
+				TRY_BREAK;
+			}
+			else if (retval)
+			{
+				result = CF_ERROR_SOCKET_CONNECT;
+				TRY_BREAK;
+			}
+		}
+		else
 		{
 			result = CF_ERROR_SOCKET_CONNECT;
@@ -269,4 +390,7 @@
 		return result;
 	}
+
+	if (timeout > CF_SOCKET_NO_TIMEOUT)
+		CF_Socket_Local_SetNonBlocking (sock, CF_FALSE);
 
 	return sock;
@@ -330,22 +454,29 @@
  *
  * @param sock		서버 소켓
- * @param address	[옵션] 클라이언트 정보를 담을 sockaddr_in 구조체 포인터
+ * @param address	[옵션] 클라이언트 정보를 담을 CF_Socket_HostInfo 구조체 포인터
+ *
+ * @see CF_Socket_HostInfo
  */
 int
 CF_Socket_Accept (const int				sock,
-				  struct sockaddr_in	* address)
-{
-	int					sockClient;
-	struct sockaddr_in	remoteAddress;
-	socklen_t			len = sizeof (remoteAddress);
+				  CF_Socket_HostInfo	* host)
+{
+	int					sockClient = 0;
+	struct sockaddr_in	address;
+	socklen_t			len = sizeof (address);
 
 	CHECK_INVALID_SOCKET (sock);
 
-	sockClient = accept (sock, (struct sockaddr *) &remoteAddress, &len);
+	sockClient = accept (sock, (struct sockaddr *) &address, &len);
 	if (sockClient < 0)
 		return CF_ERROR_SOCKET_ACCEPT;
 
-	if (address != NULL)
-		memcpy ((void *) address, (void *) &remoteAddress, sizeof (struct sockaddr_in));
+	if (host != NULL)
+	{
+		snprintf (host->address, sizeof (host->address) - 1,
+				  "%s",
+				  inet_ntoa (address.sin_addr));
+		host->port = ntohs (address.sin_port);
+	}
 
 	return sockClient;
@@ -366,4 +497,25 @@
 				const int	len)
 {
+	return CF_Socket_SendTimeout (sock, buf, len, CF_SOCKET_NO_TIMEOUT);
+}
+
+/**
+ * 타임아웃 동안 데이터 송신
+ *
+ * @return 성공 시, CF_OK; 실패 시, 오류 코드
+ *
+ * @param sock		소켓
+ * @param buf		송신할 데이터
+ * @param len		송신할 데이터의 길이
+ * @param timeout	타임아웃 (초)
+ *
+ * @see CF_SOCKET_NO_TIMEOUT
+ */
+int
+CF_Socket_SendTimeout (const int	sock,
+					   const void	* buf,
+					   const int	len,
+					   const int	timeout)
+{
 	int result = 0;
 
@@ -391,11 +543,48 @@
 				const int	len)
 {
+	return CF_Socket_RecvTimeout (sock, buf, len, CF_SOCKET_NO_TIMEOUT);
+}
+
+/**
+ * 타임아웃 동안 데이터 수신
+ *
+ * @return 성공 시, 수신한 데이터의 길이; 실패 시, 오류 코드
+ *
+ * @param sock		소켓
+ * @param buf		데이터를 수신할 버퍼
+ * @param len		데이터를 수신할 버퍼의 최대 크기
+ * @param timeout	타임아웃 (초)
+ *
+ * @see CF_SOCKET_NO_TIMEOUT
+ */
+int
+CF_Socket_RecvTimeout (const int	sock,
+					   void			* buf,
+					   const int	len,
+					   const int	timeout)
+{
 	int result = 0;
 
 	CHECK_INVALID_SOCKET (sock);
 
-	result = (int) recv (sock, buf, (size_t) len, 0);
-	if (result < 0)
-		return CF_ERROR_SOCKET_RECV;
+	TRY
+	{
+		result = CF_Socket_Local_CheckTimeout (sock, timeout);
+		if (result < 0)
+		{
+			TRY_BREAK;
+		}
+
+		result = (int) recv (sock, buf, (size_t) len, 0);
+		if (result < 0)
+		{
+			result = CF_ERROR_SOCKET_RECV;
+			TRY_BREAK;
+		}
+	}
+	CATCH_IF (result < 0)
+	{
+		return result;
+	}
 
 	return result;
Index: trunk/test/socket_client.c
===================================================================
--- trunk/test/socket_client.c	(revision 45)
+++ trunk/test/socket_client.c	(revision 46)
@@ -10,5 +10,5 @@
 int main (void) {
 	int sock = 0;
-	int recvd = 0;
+	int result = 0;
 	char buf[] = "http://unsigned.kr";
 	unsigned short port = 12345;
@@ -19,14 +19,19 @@
 	sock = CF_Socket_Connect ("localhost", port);
 	if (sock < 0) {
-		// error
+		fprintf (stderr, "error : connect (%d)\n", sock);
 	}
-	if (CF_Socket_Send (sock, buf, sizeof (buf)) < 0) {
-		// error
+
+	result = CF_Socket_Send (sock, buf, sizeof (buf));
+	if (result < 0) {
+		fprintf (stderr, "error : send (%d)\n", sock);
 	}
 	memset (buf, 0x00, strlen (buf));
-	if ((recvd = CF_Socket_Recv (sock, buf, sizeof (buf))) < 0) {
-		// error
+
+	result = CF_Socket_Recv (sock, buf, sizeof (buf));
+	if (result < 0) {
+		fprintf (stderr, "error : recv (%d)\n", result);
 	}
-	fprintf (stderr, "client recv : %s\n", buf);
+	fprintf (stderr, "client recv : %s(%d)\n", buf,, result);
+
 	CF_Socket_Close (sock);
 	CF_Socket_Finalize ();
Index: trunk/test/socket_server.c
===================================================================
--- trunk/test/socket_server.c	(revision 45)
+++ trunk/test/socket_server.c	(revision 46)
@@ -11,5 +11,5 @@
 	int clntsock = 0;
 	unsigned short port = 12345;
-	int recvd = 0;
+	int result = 0;
 	char buf[1024] = {0x00,};
 
@@ -19,17 +19,23 @@
 	srvsock = CF_Socket_Server (port, 5);
 	if (srvsock < 0) {
-		// error
+		fprintf (stderr, "error : server (%d)\n", srvsock);
 	}
+
 	clntsock = CF_Socket_Accept (srvsock, NULL);
 	if (clntsock < 0) {
-		// error
+		fprintf (stderr, "error : accept (%d)\n", clntsock);
 	}
-	if ((recvd = CF_Socket_Recv (clntsock, buf, sizeof (buf))) < 0) {
-		// error
+
+	result = CF_Socket_Recv (clntsock, buf, sizeof (buf));
+	if (result < 0) {
+		fprintf (stderr, "error : recv (%d)\n", result);
 	}
-	fprintf (stderr, "server recv : %s\n", buf);
-	if (CF_Socket_Send (clntsock, buf, recvd) < 0) {
-		// error
+	fprintf (stderr, "server recv : %s(%d)\n", buf, result);
+
+	result = CF_Socket_Send (clntsock, buf, result);
+	if (result < 0) {
+		fprintf (stderr, "error : send (%d)\n", result);
 	}
+
 	CF_Socket_Close (srvsock);
 	CF_Socket_Finalize ();
