Index: /trunk/include/cf/network.h
===================================================================
--- /trunk/include/cf/network.h	(revision 4)
+++ /trunk/include/cf/network.h	(revision 5)
@@ -20,4 +20,41 @@
 	{
 		/**
+		 * network host
+		 */
+		class host
+		{
+		private:
+			std::string mAddress;
+			cf::uint16_t mPort;
+
+		public:
+			/**
+			 * constructor
+			 * @param address host address
+			 * @param port port number
+			 */
+			host(const std::string & address = "",
+				 const cf::uint16_t port = 0);
+
+			/**
+			 * get host address
+			 * @return host address
+			 */
+			std::string address() const;
+
+			/**
+			 * get port number
+			 * @return port number
+			 */
+			cf::uint16_t port() const;
+
+			/**
+			 * is empty ?
+			 * @return true; false
+			 */
+			cf::bool_t empty() const;
+		};
+
+		/**
 		 * TCP Socket
 		 */
@@ -27,6 +64,4 @@
 			cf::socket_t mSocket;
 			cf::int32_t mTimeout;
-			std::string mHost;
-			cf::uint16_t mPort;
 
 			/**
@@ -35,5 +70,5 @@
 			 * @throw cf::exception
 			 */
-			cf::void_t receive(bin & out)
+			cf::void_t receive(bin & out) const
 				throw (cf::exception);
 
@@ -58,12 +93,10 @@
 
 			/**
-			 * connect to host:port
-			 * @param host host
-			 * @param port port
+			 * connect to address:port
+			 * @param peer peer host
 			 * @param timeout timeout
 			 * @throw cf::exception
 			 */
-			cf::void_t connect(const cf::char_t * host,
-							   const cf::uint16_t port,
+			cf::void_t connect(const host & peer,
 							   const cf::int32_t timeout = 0)
 				throw (cf::exception);
@@ -76,5 +109,5 @@
 			 */
 			cf::void_t listen(const cf::uint16_t port,
-							  const cf::int32_t backlog = 5)
+							  const cf::int32_t backlog = 5) const
 				throw (cf::exception);
 
@@ -84,5 +117,5 @@
 			 * @throw cf::exception
 			 */
-			tcp accept()
+			tcp accept() const
 				throw (cf::exception);
 
@@ -108,5 +141,5 @@
 			 * @throw cf::exception
 			 */
-			cf::void_t send(const bin & in)
+			cf::void_t send(const bin & in) const
 				throw (cf::exception);
 
@@ -117,5 +150,5 @@
 			 * @throw cf::exception
 			 */
-			bin receive(const cf::int32_t size)
+			bin receive(const cf::int32_t size) const
 				throw (cf::exception);
 
@@ -125,5 +158,5 @@
 			 * @throw cf::exception
 			 */
-			bin receive()
+			bin receive() const
 				throw (cf::exception);
 
@@ -133,5 +166,5 @@
 			cf::void_t getOption(const cf::int32_t optname,
 								 cf::void_t * optval,
-								 cf::int32_t * optlen)
+								 cf::int32_t * optlen) const
 				throw (cf::exception);
 
@@ -141,13 +174,6 @@
 			cf::void_t setOption(const cf::int32_t optname,
 								 const cf::void_t * optval,
-								 const cf::int32_t optlen)
-				throw (cf::exception);
-
-			/**
-			 * set non-blocking
-			 * @param flag true; false
-			 * @see setTimeout
-			 */
-			cf::void_t setNonBlocking(const cf::bool_t flag);
+								 const cf::int32_t optlen) const
+				throw (cf::exception);
 
 			/**
@@ -157,4 +183,20 @@
 			 */
 			cf::void_t setTimeout(const cf::int32_t seconds);
+
+			/**
+			 * get local host
+			 * @return local host
+			 * @see cf::network::host
+			 */
+			host local() const
+				throw (cf::exception);
+
+			/**
+			 * get peer host
+			 * @return peer host
+			 * @see cf::network::host
+			 */
+			host peer() const
+				throw (cf::exception);
 		};
 
Index: /trunk/src/network.cpp
===================================================================
--- /trunk/src/network.cpp	(revision 4)
+++ /trunk/src/network.cpp	(revision 5)
@@ -37,7 +37,5 @@
 #endif
 
-#define ALLOW_SOCKET_TIME_WAIT
-
-cf::socket_t gInvalidSocket	= -1;
+#define INVALID_SOCKET	-1
 
 /*--------------------------------------------------------------*/
@@ -48,4 +46,34 @@
 long GetMACAddress(cf::char_t *addr);
 
+static std::string convertAddressToString(struct sockaddr_in & addr)
+{
+	cf::uint8_t * bytes = NULL;
+	cf::char_t str[32] = {0x00};
+
+	bytes = reinterpret_cast<cf::uint8_t *>(&addr.sin_addr.s_addr);
+	snprintf(str, sizeof(str) - 1, "%u.%u.%u.%u", bytes[0],
+												  bytes[1],
+												  bytes[2],
+												  bytes[3]);
+
+	return str;
+}
+
+static cf::void_t setNonBlocking(const cf::socket_t sock,
+								 const cf::bool_t flag)
+{
+#ifdef _ON_WINDOWS
+	cf::ulong_t mode = flag ? 1 : 0;
+	ioctlsocket(sock, FIONBIO, &mode);
+#else
+	cf::int32_t mode = fcntl(sock, F_GETFL, 0);
+
+	if (flag)	mode |=  O_NONBLOCK;
+	else		mode &= ~O_NONBLOCK;
+
+	fcntl(sock, F_SETFL, mode);
+#endif
+}
+
 static cf::void_t waitForTimeout(const cf::socket_t sock,
 								 const cf::int32_t timeout,
@@ -87,18 +115,12 @@
 }
 
-static cf::void_t setLinger(cf::network::tcp & tcp)
-	throw (cf::exception)
-{
-#ifdef ALLOW_SOCKET_TIME_WAIT
-	return;
-#else
+static cf::void_t setReuseAddress(const cf::network::tcp & tcp)
+	throw (cf::exception)
+{
 	try
 	{
-		struct linger linger;
-
-		linger.l_onoff = 1;
-		linger.l_linger = 0;
-
-		tcp.setOption(SO_LINGER, &linger, sizeof(linger));
+		cf::int32_t reuseaddr = 1;
+
+		tcp.setOption(SO_REUSEADDR, &reuseaddr, sizeof(reuseaddr));
 	}
 	catch (cf::exception & e)
@@ -106,22 +128,49 @@
 		FORWARD_EXCEPTION(e);
 	}
-#endif
-}
-
-static cf::void_t setReuseAddress(cf::network::tcp & tcp)
-	throw (cf::exception)
-{
-	try
-	{
-		cf::int32_t reuseaddr = 1;
-
-		tcp.setOption(SO_REUSEADDR, &reuseaddr, sizeof(reuseaddr));
-	}
-	catch (cf::exception & e)
-	{
-		FORWARD_EXCEPTION(e);
-	}
+}
+
+typedef cf::int32_t (*getSocketNameAPI)(cf::socket_t sock,
+										struct sockaddr * addr,
+										socklen_t *len);
+
+static cf::network::host getSocketNameFromFunction(const cf::socket_t sock,
+												   getSocketNameAPI api)
+	throw (cf::exception)
+{
+	cf::int32_t result = 0;
+	struct sockaddr_in addr;
+	socklen_t len = sizeof(struct sockaddr_in);
+
+	result = api(sock, (struct sockaddr *)&addr, &len);
+	if (result < 0)
+		THROW_EXCEPTION("cannot get sockket or peer name ("
+						<< cf::exception::systemCode()
+						<< ")");
+
+	return cf::network::host(convertAddressToString(addr), addr.sin_port);
 }
 /*--------------------------------------------------------------*/
+
+cf::network::host::host(const std::string & address,
+						const cf::uint16_t port)
+	: mAddress(address),
+	  mPort(port)
+{
+}
+
+std::string cf::network::host::address() const
+{
+	return mAddress;
+}
+
+cf::uint16_t cf::network::host::port() const
+{
+	return mPort;
+}
+
+cf::bool_t cf::network::host::empty() const
+{
+	return (address().empty() || port() <= 0) ? true : false;
+}
 
 cf::network::tcp::tcp(const cf::socket_t attachedSocket)
@@ -145,5 +194,5 @@
 	}
 
-	if (mSocket == gInvalidSocket)
+	if (mSocket == INVALID_SOCKET)
 		mSocket = ::socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
 
@@ -159,20 +208,17 @@
 cf::void_t cf::network::tcp::close()
 {
-	if (mSocket == gInvalidSocket)
+	if (mSocket == INVALID_SOCKET)
 		return;
 
 	closesocket(mSocket);
 
-	mSocket = gInvalidSocket;
-	mHost = "";
-	mPort = 0;
-}
-
-cf::void_t cf::network::tcp::connect(const cf::char_t * host,
-									 const cf::uint16_t port,
+	mSocket = INVALID_SOCKET;
+}
+
+cf::void_t cf::network::tcp::connect(const cf::network::host & peer,
 									 const cf::int32_t timeout)
 	throw (cf::exception)
 {
-	if (!host || !port)
+	if (peer.empty())
 		THROW_EXCEPTION("invalid host info");
 
@@ -183,4 +229,7 @@
 	struct hostent * hostEnt;
 
+	const cf::char_t * host = peer.address().c_str();
+	cf::uint16_t port = peer.port();
+
 	/* 1. set data */
 	addr.sin_family			= AF_INET;
@@ -204,5 +253,4 @@
 	try
 	{
-		setLinger(*this);
 		setReuseAddress(*this);
 	}
@@ -212,6 +260,5 @@
 	}
 
-	if (timeout > 0)
-		setNonBlocking(true);
+	setTimeout(timeout);
 
 	/* 4. connect */
@@ -243,13 +290,8 @@
 		}
 	}
-
-	/* set */
-	mHost = host;
-	mPort = port;
-	mTimeout = timeout;
 }
 
 cf::void_t cf::network::tcp::listen(const cf::uint16_t port,
-									const cf::int32_t backlog)
+									const cf::int32_t backlog) const
 	throw (cf::exception)
 {
@@ -268,5 +310,4 @@
 	try
 	{
-		setLinger(*this);
 		setReuseAddress(*this);
 	}
@@ -285,5 +326,5 @@
 }
 
-cf::network::tcp cf::network::tcp::accept()
+cf::network::tcp cf::network::tcp::accept() const
 	throw (cf::exception)
 {
@@ -302,5 +343,5 @@
 	throw (exception)
 {
-	if (sock == gInvalidSocket)
+	if (sock == INVALID_SOCKET)
 		THROW_EXCEPTION("has invalid socket");
 
@@ -313,15 +354,15 @@
 	throw (exception)
 {
-	if (mSocket == gInvalidSocket)
+	if (mSocket == INVALID_SOCKET)
 		THROW_EXCEPTION("has invalid socket");
 
 	cf::socket_t sock = mSocket;
 
-	mSocket = gInvalidSocket;
+	mSocket = INVALID_SOCKET;
 
 	return sock;
 }
 
-cf::void_t cf::network::tcp::send(const cf::bin & in)
+cf::void_t cf::network::tcp::send(const cf::bin & in) const
 	throw (cf::exception)
 {
@@ -337,5 +378,5 @@
 }
 
-cf::void_t cf::network::tcp::receive(cf::bin & out)
+cf::void_t cf::network::tcp::receive(cf::bin & out) const
 	throw (cf::exception)
 {
@@ -364,5 +405,5 @@
 }
 
-cf::bin cf::network::tcp::receive(const cf::int32_t size)
+cf::bin cf::network::tcp::receive(const cf::int32_t size) const
 	throw (cf::exception)
 {
@@ -375,5 +416,5 @@
 }
 
-cf::bin cf::network::tcp::receive()
+cf::bin cf::network::tcp::receive() const
 	throw (cf::exception)
 {
@@ -396,5 +437,5 @@
 cf::void_t cf::network::tcp::getOption(const cf::int32_t optname,
 									   cf::void_t * optval,
-									   cf::int32_t * optlen)
+									   cf::int32_t * optlen) const
 	throw (cf::exception)
 {
@@ -416,5 +457,5 @@
 cf::void_t cf::network::tcp::setOption(const cf::int32_t optname,
 									   const cf::void_t * optval,
-									   const cf::int32_t optlen)
+									   const cf::int32_t optlen) const
 	throw (cf::exception)
 {
@@ -434,22 +475,34 @@
 }
 
-cf::void_t cf::network::tcp::setNonBlocking(const cf::bool_t flag)
-{
-#ifdef _ON_WINDOWS
-	cf::ulong_t mode = flag ? 1 : 0;
-	ioctlsocket(mSocket, FIONBIO, &mode);
-#else
-	cf::int32_t mode = fcntl(mSocket, F_GETFL, 0);
-
-	if (flag)	mode |=  O_NONBLOCK;
-	else		mode &= ~O_NONBLOCK;
-
-	fcntl(mSocket, F_SETFL, mode);
-#endif
-}
-
 cf::void_t cf::network::tcp::setTimeout(const cf::int32_t seconds)
 {
+	setNonBlocking(mSocket, seconds > 0 /*? true : false*/);
 	mTimeout = seconds;
+}
+
+cf::network::host cf::network::tcp::peer() const
+	throw (cf::exception)
+{
+	try
+	{
+		return getSocketNameFromFunction(mSocket, getpeername);
+	}
+	catch (cf::exception & e)
+	{
+		FORWARD_EXCEPTION(e);
+	}
+}
+
+cf::network::host cf::network::tcp::local() const
+	throw (cf::exception)
+{
+	try
+	{
+		return getSocketNameFromFunction(mSocket, getsockname);
+	}
+	catch (cf::exception & e)
+	{
+		FORWARD_EXCEPTION(e);
+	}
 }
 
Index: /trunk/test/test.cpp
===================================================================
--- /trunk/test/test.cpp	(revision 4)
+++ /trunk/test/test.cpp	(revision 5)
@@ -213,4 +213,9 @@
 		{
 			client.attach(server.accept().detach());
+			cf::network::host peer = client.peer();
+			std::cout << "client <"
+					  << peer.address() << ":" << peer.port()
+					  << "> is connected"
+					  << std::endl;
 			msg = client.receive();
 			client.send(msg);
@@ -237,9 +242,11 @@
 	{
 		cf::network::tcp client;
+		cf::network::host host(HOST, PORT);
+
 		cf::ulong_t tid = cf::task::thread::id();
 		cf::bin msg(STR(STRING << " " << tid).c_str());
 		cf::bin response;
 
-		client.connect(HOST, PORT, TIMEOUT);
+		client.connect(host, TIMEOUT);
 		client.send(msg);
 		response = client.receive();
