diff --git a/Cargo.toml b/Cargo.toml
index 22ff7f1bbeba5de5c04a68a8a17d5c38acf6f82f..4b656fb56c80665f7ea141c51e4c8728f83b1219 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "coap"
-version = "0.3.1"
+version = "0.4.0"
 description = "A CoAP library"
 readme = "README.md"
 documentation = "http://covertness.github.io/coap-rs/coap/index.html"
@@ -17,6 +17,7 @@ threadpool = "0.1"
 url = "0.2.36"
 num = "0.1"
 rand = "0.3"
+log = "0.3"
 
 [dev-dependencies]
-quickcheck = "*"
\ No newline at end of file
+quickcheck = "*"
diff --git a/LICENSE b/LICENSE
index 23b5b4099ba4ecb013ed93295c6ffb0cbc059810..970e986dd325b8baa3e808c0b842b6fc2aaf916c 100644
--- a/LICENSE
+++ b/LICENSE
@@ -1,4 +1,4 @@
-Copyright (c) 2014 Sean McArthur
+Copyright (c) 2014-2016 Yang Zhang
 
 Permission is hereby granted, free of charge, to any person obtaining a copy
 of this software and associated documentation files (the "Software"), to deal
@@ -16,4 +16,4 @@ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-THE SOFTWARE.
\ No newline at end of file
+THE SOFTWARE.
diff --git a/README.md b/README.md
index 025c07f19af1da296f25745bdb9fb34aa87faf2d..8c46e80ce04fdd7d8ca23656f33f289f77e8c936 100644
--- a/README.md
+++ b/README.md
@@ -17,7 +17,7 @@ First add this to your `Cargo.toml`:
 
 ```toml
 [dependencies]
-coap = "0.3"
+coap = "0.4"
 ```
 
 Then, add this to your crate root:
@@ -36,8 +36,9 @@ use std::io;
 use coap::packet::*;
 use coap::{CoAPServer, CoAPClient};
 
-fn request_handler(req: Packet, _resp: CoAPClient) {
+fn request_handler(req: Packet, response: Option<Packet>) -> Option<Packet> {
 	println!("Receive request: {:?}", req);
+	response
 }
 
 fn main() {
@@ -45,7 +46,7 @@ fn main() {
 
 	let mut server = CoAPServer::new(addr).unwrap();
 	server.handle(request_handler).unwrap();
-		
+
 	println!("Server up on {}", addr);
     println!("Press any key to stop...");
 	io::stdin().read_line(&mut String::new()).unwrap();
diff --git a/examples/client.rs b/examples/client.rs
index aa3d135fe9f7209149b4c2f395c32bd89c9b7281..865a56c37a4838d4bd8360b714caa5e16c3824cb 100644
--- a/examples/client.rs
+++ b/examples/client.rs
@@ -31,4 +31,4 @@ fn main() {
 			}
 		}
 	}
-}
\ No newline at end of file
+}
diff --git a/examples/client_and_server.rs b/examples/client_and_server.rs
index b8550e3786331fed1fd9b7f46b6b2b917af2e96c..1d5fb6e0baf80e296e609ff41750810e8670ec93 100644
--- a/examples/client_and_server.rs
+++ b/examples/client_and_server.rs
@@ -3,18 +3,25 @@ extern crate coap;
 use coap::packet::*;
 use coap::{CoAPServer, CoAPClient};
 
-fn request_handler(req: Packet, resp: CoAPClient) {
+fn request_handler(req: Packet, response: Option<Packet>) -> Option<Packet> {
 	let uri_path = req.get_option(OptionType::UriPath).unwrap();
-	resp.reply(&req, uri_path.front().unwrap().clone()).unwrap();
+
+	return match response {
+		Some(mut packet) => {
+			packet.set_payload(uri_path.front().unwrap().clone());
+			Some(packet)
+		},
+		_ => None
+    };
 }
 
 fn main() {
 	let mut server = CoAPServer::new("127.0.0.1:5683").unwrap();
 	server.handle(request_handler).unwrap();
-		
+
 	let url = "coap://127.0.0.1:5683/Rust";
 	println!("Client request: {}", url);
 
 	let response: Packet = CoAPClient::request(url).unwrap();
 	println!("Server reply: {}", String::from_utf8(response.payload).unwrap());
-}
\ No newline at end of file
+}
diff --git a/examples/server.rs b/examples/server.rs
index b33505b45ba16ccf49971831cad96b246e55bd59..887e4ae3b282a3d2dee641751d1304bc59c64054 100644
--- a/examples/server.rs
+++ b/examples/server.rs
@@ -2,11 +2,16 @@ extern crate coap;
 
 use std::io;
 use coap::packet::*;
-use coap::{CoAPServer, CoAPClient};
+use coap::CoAPServer;
 
-fn request_handler(req: Packet, resp: CoAPClient) {
-	println!("Receive request: {:?}", req);
-	resp.reply(&req, b"OK".to_vec()).unwrap();
+fn request_handler(_: Packet, response: Option<Packet>) -> Option<Packet> {
+	return match response {
+		Some(mut packet) => {
+			packet.set_payload(b"OK".to_vec());
+			Some(packet)
+		},
+		_ => None
+	};
 }
 
 fn main() {
@@ -14,11 +19,11 @@ fn main() {
 
 	let mut server = CoAPServer::new(addr).unwrap();
 	server.handle(request_handler).unwrap();
-		
+
 	println!("Server up on {}", addr);
 	println!("Press any key to stop...");
 
 	io::stdin().read_line(&mut String::new()).unwrap();
 
 	println!("Server shutdown");
-}
\ No newline at end of file
+}
diff --git a/src/client.rs b/src/client.rs
index b2846baabd49b2741a2dff437868e1f99becd7e5..84b8617903113c191efb4e1e136fe611c0ee0d4d 100644
--- a/src/client.rs
+++ b/src/client.rs
@@ -9,8 +9,8 @@ use packet::{Packet, PacketType, OptionType};
 const DEFAULT_RECEIVE_TIMEOUT: u64 = 5;  // 5s
 
 pub struct CoAPClient {
-    socket: UdpSocket,
-    peer_addr: SocketAddr,
+	socket: UdpSocket,
+	peer_addr: SocketAddr,
 }
 
 impl CoAPClient {
@@ -60,7 +60,7 @@ impl CoAPClient {
 
 				let mut token: Vec<u8> = vec!(1, 1, 1, 1);
 				for x in token.iter_mut() {
-				    *x = random()
+					*x = random()
 				}
 				packet.set_token(token.clone());
 
@@ -81,15 +81,15 @@ impl CoAPClient {
 
 				try!(client.set_receive_timeout(timeout));
 				match client.receive() {
-				 	Ok(receive_packet) => {
-				 		if receive_packet.header.get_message_id() == message_id 
-				 			&& *receive_packet.get_token() == token {
-				 				return Ok(receive_packet)
-				 			} else {
-				 				return Err(Error::new(ErrorKind::Other, "receive invalid data"))
-				 			}
-				 	},
-				 	Err(e) => Err(e)
+					Ok(receive_packet) => {
+						if receive_packet.header.get_message_id() == message_id
+							&& *receive_packet.get_token() == token {
+								return Ok(receive_packet)
+							} else {
+								return Err(Error::new(ErrorKind::Other, "receive invalid data"))
+							}
+					},
+					Err(e) => Err(e)
 				}
 			},
 			Err(_) => Err(Error::new(ErrorKind::InvalidInput, "url error"))
@@ -101,24 +101,6 @@ impl CoAPClient {
 		Self::request_with_timeout(url, Some(Duration::new(DEFAULT_RECEIVE_TIMEOUT, 0)))
 	}
 
-	/// Response the client with the specifc payload.
-	pub fn reply(&self, request_packet: &Packet, payload: Vec<u8>) -> Result<()> {
-		let mut packet = Packet::new();
-
-		packet.header.set_version(1);
-		let response_type = match request_packet.header.get_type() {
-			PacketType::Confirmable => PacketType::Acknowledgement,
-			PacketType::NonConfirmable => PacketType::NonConfirmable,
-			_ => return Err(Error::new(ErrorKind::InvalidInput, "request type error"))
-		};
-		packet.header.set_type(response_type);
-		packet.header.set_code("2.05");
-		packet.header.set_message_id(request_packet.header.get_message_id());
-		packet.set_token(request_packet.get_token().clone());
-		packet.payload = payload;
-		self.send(&packet)
-	}
-
 	/// Execute a request.
 	pub fn send(&self, packet: &Packet) -> Result<()> {
 		match packet.to_bytes() {
@@ -147,7 +129,7 @@ impl CoAPClient {
 
 	/// Set the receive timeout.
 	pub fn set_receive_timeout(&self, dur: Option<Duration>) -> Result<()> {
-	    self.socket.set_read_timeout(dur)
+		self.socket.set_read_timeout(dur)
 	}
 
 	fn coap_scheme_type_mapper(scheme: &str) -> SchemeType {
@@ -164,7 +146,7 @@ mod test {
 	use super::*;
 	use std::time::Duration;
 	use std::io::ErrorKind;
-	use packet::{Packet, PacketType};
+	use packet::Packet;
 	use server::CoAPServer;
 
 	#[test]
@@ -174,15 +156,8 @@ mod test {
 		assert!(CoAPClient::request("127.0.0.1").is_err());
 	}
 
-	#[test]
-	fn test_reply_error() {
-		let client = CoAPClient::new("127.0.0.1:5683").unwrap();
-		let mut packet = Packet::new();
-		packet.header.set_type(PacketType::Acknowledgement);
-		assert!(client.reply(&packet, b"Test".to_vec()).is_err());
-	}
-
-	fn request_handler(_: Packet, _: CoAPClient) {
+	fn request_handler(_: Packet, _:Option<Packet>) -> Option<Packet> {
+		None
 	}
 
 	#[test]
@@ -197,4 +172,4 @@ mod test {
 			assert_eq!(error.kind(), ErrorKind::WouldBlock);
 		}
 	}
-}
\ No newline at end of file
+}
diff --git a/src/lib.rs b/src/lib.rs
index 14fc6b9c469ace69ae870349487f61c1bab30827..6d7483e72869e17a41bca9ae68d17e4fc6ccb672 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -3,16 +3,16 @@
 //! This library provides both a client interface (`CoAPClient`) and a server interface (`CoAPServer`).
 //!
 //! [spec]: https://tools.ietf.org/html/rfc7252
-//! 
+//!
 //! # Installation
-//! 
+//!
 //! First add this to your `Cargo.toml`:
-//! 
+//!
 //! ```toml
 //! [dependencies]
 //! coap = "0.3"
 //! ```
-//! 
+//!
 //! Then, add this to your crate root:
 //!
 //! ```
@@ -29,21 +29,22 @@
 //! use coap::packet::*;
 //! use coap::{CoAPServer, CoAPClient};
 
-//! fn request_handler(req: Packet, _resp: CoAPClient) {
+//! fn request_handler(req: Packet, resp: Option<Packet>) -> Option<Packet> {
 //! 	println!("Receive request: {:?}", req);
+//!     None
 //! }
 
 //! fn main() {
 //! 	let addr = "127.0.0.1:5683";
-//! 
+//!
 //! 	let mut server = CoAPServer::new(addr).unwrap();
 //! 	server.handle(request_handler).unwrap();
-//! 		
+//!
 //! 	println!("Server up on {}", addr);
 //!     println!("Press any key to stop...");
 //!
 //! 	io::stdin().read_line(&mut String::new()).unwrap();
-//! 
+//!
 //! 	println!("Server shutdown");
 //! }
 //! ```
@@ -73,9 +74,12 @@ extern crate num;
 extern crate rand;
 #[cfg(test)] extern crate quickcheck;
 
+#[macro_use]
+extern crate log;
+
 pub use server::CoAPServer;
 pub use client::CoAPClient;
 
 pub mod packet;
 pub mod client;
-pub mod server;
\ No newline at end of file
+pub mod server;
diff --git a/src/packet.rs b/src/packet.rs
index c2a8b09dd2b570c4c641aef03aeaed6f8a9acbe6..103a54e50348fdb123f94bd04e1ebe020670b305 100644
--- a/src/packet.rs
+++ b/src/packet.rs
@@ -3,25 +3,25 @@ use std::collections::BTreeMap;
 use std::collections::LinkedList;
 
 macro_rules! u8_to_unsigned_be {
-    ($src:ident, $start:expr, $end:expr, $t:ty) => ({
-        (0 .. $end - $start + 1).rev().fold(0, |acc, i| acc | $src[$start+i] as $t << i * 8)
-    })
+	($src:ident, $start:expr, $end:expr, $t:ty) => ({
+		(0 .. $end - $start + 1).rev().fold(0, |acc, i| acc | $src[$start+i] as $t << i * 8)
+	})
 }
 
 #[derive(PartialEq, Eq, Debug)]
 pub enum PacketType {
-    Confirmable,
-    NonConfirmable,
-    Acknowledgement,
-    Reset,
-    Invalid,
+	Confirmable,
+	NonConfirmable,
+	Acknowledgement,
+	Reset,
+	Invalid,
 }
 
 #[derive(Default, Debug, RustcEncodable, RustcDecodable)]
 pub struct PacketHeader {
-    ver_type_tkl: u8,
-    code: u8,
-    message_id: u16
+	ver_type_tkl: u8,
+	code: u8,
+	message_id: u16
 }
 
 impl PacketHeader {
@@ -108,9 +108,9 @@ impl PacketHeader {
 #[derive(Debug)]
 pub enum ParseError {
 	InvalidHeader,
-    InvalidTokenLength,
-    InvalidOptionDelta,
-    InvalidOptionLength,
+	InvalidTokenLength,
+	InvalidOptionDelta,
+	InvalidOptionLength,
 }
 
 #[derive(Debug)]
@@ -121,32 +121,32 @@ pub enum PackageError {
 
 #[derive(PartialEq, Eq, Debug)]
 pub enum OptionType {
-    IfMatch,
-    UriHost,
-    ETag,
-    IfNoneMatch,
-    Observe,
-    UriPort,
-    LocationPath,
-    UriPath,
-    ContentFormat,
-    MaxAge,
-    UriQuery,
-    Accept,
-    LocationQuery,
-    Block2,
-    Block1,
-    ProxyUri,
-    ProxyScheme,
-    Size1
+	IfMatch,
+	UriHost,
+	ETag,
+	IfNoneMatch,
+	Observe,
+	UriPort,
+	LocationPath,
+	UriPath,
+	ContentFormat,
+	MaxAge,
+	UriQuery,
+	Accept,
+	LocationQuery,
+	Block2,
+	Block1,
+	ProxyUri,
+	ProxyScheme,
+	Size1
 }
 
 #[derive(Debug)]
 pub struct Packet {
-    pub header: PacketHeader,
-    token: Vec<u8>,
-    options: BTreeMap<usize, LinkedList<Vec<u8>>>,
-    pub payload: Vec<u8>,
+	pub header: PacketHeader,
+	token: Vec<u8>,
+	options: BTreeMap<usize, LinkedList<Vec<u8>>>,
+	pub payload: Vec<u8>,
 }
 
 impl Packet {
@@ -173,6 +173,10 @@ impl Packet {
 		self.options.insert(num, value);
 	}
 
+	pub fn set_payload(&mut self, payload: Vec<u8>){
+		self.payload = payload;
+	}
+
 	pub fn add_option(&mut self, tp: OptionType, value: Vec<u8>) {
 		let num = Self::get_option_number(tp);
 		match self.options.get_mut(&num) {
@@ -188,9 +192,12 @@ impl Packet {
 		self.options.insert(num, list);
 	}
 
-	pub fn get_option(&self, tp: OptionType) -> Option<&LinkedList<Vec<u8>>> {
+	pub fn get_option(&self, tp: OptionType) -> Option<LinkedList<Vec<u8>>> {
 		let num = Self::get_option_number(tp);
-		return self.options.get(&num);
+		match self.options.get(&num) {
+			Some(options) => Some(options.clone()),
+			None => None
+		}
 	}
 
 	/// Decodes a byte slice and construct the equivalent Packet.
@@ -226,40 +233,52 @@ impl Packet {
 
 					idx += 1;
 
-					if delta == 13 {
-						if idx >= buf.len() {
-							return Err(ParseError::InvalidOptionLength);
+					// Check for special delta characters
+					match delta {
+						13 => {
+							if idx >= buf.len() {
+								return Err(ParseError::InvalidOptionLength);
+							}
+							delta = buf[idx] as usize + 13;
+							idx += 1;
+						},
+						14 => {
+							if idx + 1 >= buf.len() {
+								return Err(ParseError::InvalidOptionLength);
+							}
+
+							delta = (u16::from_be(u8_to_unsigned_be!(buf, idx, idx + 1, u16)) + 269) as usize;
+							idx += 2;
+						},
+						15 => {
+							return Err(ParseError::InvalidOptionDelta);
 						}
-						delta = buf[idx] as usize + 13;
-						idx += 1;
-					} else if delta == 14 {
-						if idx + 1 >= buf.len() {
+						_ => {}
+					};
+
+					// Check for special length characters
+					match length {
+						13 => {
+							if idx >= buf.len() {
+								return Err(ParseError::InvalidOptionLength);
+							}
+
+							length = buf[idx] as usize + 13;
+							idx += 1;
+						},
+						14 => {
+							if idx + 1 >= buf.len() {
+								return Err(ParseError::InvalidOptionLength);
+							}
+
+							length = (u16::from_be(u8_to_unsigned_be!(buf, idx, idx + 1, u16)) + 269) as usize;
+							idx += 2;
+						},
+						15 => {
 							return Err(ParseError::InvalidOptionLength);
-						}
-
-						delta = (u16::from_be(u8_to_unsigned_be!(buf, idx, idx + 1, u16)) + 269) as usize;
-						idx += 2;
-					} else if delta == 15 {
-						return Err(ParseError::InvalidOptionDelta);
-					}
-
-					if length == 13 {
-						if idx >= buf.len() {
-							return Err(ParseError::InvalidOptionLength);
-						}
-
-						length = buf[idx] as usize + 13;
-						idx += 1;
-					} else if length == 14 {
-						if idx + 1 >= buf.len() {
-							return Err(ParseError::InvalidOptionLength);
-						}
-
-						length = (u16::from_be(u8_to_unsigned_be!(buf, idx, idx + 1, u16)) + 269) as usize;
-						idx += 2;
-					} else if length == 15 {
-						return Err(ParseError::InvalidOptionLength);
-					}
+						},
+						_ => {}
+					};
 
 					options_number += delta;
 
@@ -343,14 +362,14 @@ impl Packet {
 				options_delta_length += delta;
 
 				options_bytes.reserve(header.len() + value.len());
-		        unsafe {
-		        	use std::ptr;
-		            let buf_len = options_bytes.len();
-		            ptr::copy(header.as_ptr(), options_bytes.as_mut_ptr().offset(buf_len as isize), header.len());
-		            ptr::copy(value.as_ptr(), options_bytes.as_mut_ptr().offset((buf_len + header.len()) as isize), value.len());
-		            options_bytes.set_len(buf_len + header.len() + value.len());
-		        }
-		    }
+				unsafe {
+					use std::ptr;
+					let buf_len = options_bytes.len();
+					ptr::copy(header.as_ptr(), options_bytes.as_mut_ptr().offset(buf_len as isize), header.len());
+					ptr::copy(value.as_ptr(), options_bytes.as_mut_ptr().offset((buf_len + header.len()) as isize), value.len());
+					options_bytes.set_len(buf_len + header.len() + value.len());
+				}
+			}
 		}
 
 		let mut buf_length = 4 + self.payload.len() + self.token.len();
@@ -368,23 +387,23 @@ impl Packet {
 		match header_result {
 			Ok(_) => {
 				buf.reserve(self.token.len() + options_bytes.len());
-		        unsafe {
-		        	use std::ptr;
-		            let buf_len = buf.len();
-		            ptr::copy(self.token.as_ptr(), buf.as_mut_ptr().offset(buf_len as isize), self.token.len());
-		            ptr::copy(options_bytes.as_ptr(), buf.as_mut_ptr().offset((buf_len + self.token.len()) as isize), options_bytes.len());
-		            buf.set_len(buf_len + self.token.len() + options_bytes.len());
-		        }
+				unsafe {
+					use std::ptr;
+					let buf_len = buf.len();
+					ptr::copy(self.token.as_ptr(), buf.as_mut_ptr().offset(buf_len as isize), self.token.len());
+					ptr::copy(options_bytes.as_ptr(), buf.as_mut_ptr().offset((buf_len + self.token.len()) as isize), options_bytes.len());
+					buf.set_len(buf_len + self.token.len() + options_bytes.len());
+				}
 
 				if self.header.get_code() != "0.00" && self.payload.len() != 0 {
 					buf.push(0xFF);
 					buf.reserve(self.payload.len());
-			        unsafe {
-			        	use std::ptr;
-			            let buf_len = buf.len();
-			            ptr::copy(self.payload.as_ptr(), buf.as_mut_ptr().offset(buf.len() as isize), self.payload.len());
-			            buf.set_len(buf_len + self.payload.len());
-			        }
+					unsafe {
+						use std::ptr;
+						let buf_len = buf.len();
+						ptr::copy(self.payload.as_ptr(), buf.as_mut_ptr().offset(buf.len() as isize), self.payload.len());
+						buf.set_len(buf_len + self.payload.len());
+					}
 				}
 				Ok(buf)
 			},
@@ -416,6 +435,26 @@ impl Packet {
 	}
 }
 
+/// Convert a request to a response
+pub fn auto_response(request_packet: &Packet) -> Option<Packet> {
+		let mut packet = Packet::new();
+
+		packet.header.set_version(1);
+		let response_type = match request_packet.header.get_type() {
+			PacketType::Confirmable => PacketType::Acknowledgement,
+			PacketType::NonConfirmable => PacketType::NonConfirmable,
+			_ => return None
+		};
+		packet.header.set_type(response_type);
+		packet.header.set_code("2.05");
+		packet.header.set_message_id(request_packet.header.get_message_id());
+		packet.set_token(request_packet.get_token().clone());
+
+		packet.payload = request_packet.payload.clone();
+
+		Some(packet)
+	}
+
 #[cfg(test)]
 mod test {
 	use super::*;
@@ -441,14 +480,14 @@ mod test {
 		let mut expected_uri_path = LinkedList::new();
 		expected_uri_path.push_back("Hi".as_bytes().to_vec());
 		expected_uri_path.push_back("Test".as_bytes().to_vec());
-		assert_eq!(*uri_path, expected_uri_path);
+		assert_eq!(uri_path, expected_uri_path);
 
 		let uri_query = packet.get_option(OptionType::UriQuery);
 		assert!(uri_query.is_some());
 		let uri_query = uri_query.unwrap();
 		let mut expected_uri_query = LinkedList::new();
 		expected_uri_query.push_back("a=1".as_bytes().to_vec());
-		assert_eq!(*uri_query, expected_uri_query);
+		assert_eq!(uri_query, expected_uri_query);
 	}
 
 	#[test]
diff --git a/src/server.rs b/src/server.rs
index 54514a8dcefdf98c07c82594c6eb8ebaf9377b7a..f71c21112ca0afb8621a9e20aec1f683b1ffb6d5 100644
--- a/src/server.rs
+++ b/src/server.rs
@@ -1,14 +1,16 @@
 use std;
+use std::io::{Error, ErrorKind};
 use std::thread;
-use std::net::ToSocketAddrs;
+use std::net::{ToSocketAddrs, SocketAddr};
 use std::sync::mpsc;
-use mio::*;
+use mio::{EventLoop, PollOpt, EventSet, Handler, Sender, Token};
 use mio::udp::UdpSocket;
-use packet::Packet;
-use client::CoAPClient;
+use packet::{Packet, auto_response};
 use threadpool::ThreadPool;
 
 const DEFAULT_WORKER_NUM: usize = 4;
+pub type TxQueue = mpsc::Sender<CoAPResponse>;
+pub type RxQueue = mpsc::Receiver<CoAPResponse>;
 
 #[derive(Debug)]
 pub enum CoAPServerError {
@@ -17,27 +19,35 @@ pub enum CoAPServerError {
 	AnotherHandlerIsRunning,
 }
 
+#[derive(Debug)]
+pub struct CoAPResponse {
+	pub address: SocketAddr,
+	pub response: Packet
+}
+
 pub trait CoAPHandler: Sync + Send + Copy {
-	fn handle(&self, Packet, CoAPClient);
+	fn handle(&self, Packet, Option<Packet>) -> Option<Packet>;
 }
 
-impl<F> CoAPHandler for F where F: Fn(Packet, CoAPClient), F: Sync + Send + Copy {
-	fn handle(&self, request: Packet, response: CoAPClient) {
-		self(request, response);
+impl<F> CoAPHandler for F where F: Fn(Packet, Option<Packet>) -> Option<Packet>, F: Sync + Send + Copy {
+	fn handle(&self, request: Packet, response: Option<Packet>) -> Option<Packet> {
+		return self(request, response);
 	}
 }
 
 struct UdpHandler<H: CoAPHandler + 'static> {
 	socket: UdpSocket,
 	thread_pool: ThreadPool,
+	tx_sender: TxQueue,
 	coap_handler: H
 }
 
 impl<H: CoAPHandler + 'static> UdpHandler<H> {
-	fn new(socket: UdpSocket, thread_pool: ThreadPool, coap_handler: H) -> UdpHandler<H> {
+	fn new(socket: UdpSocket, thread_pool: ThreadPool, tx_sender: TxQueue, coap_handler: H) -> UdpHandler<H> {
 		UdpHandler {
 			socket: socket,
 			thread_pool: thread_pool,
+			tx_sender: tx_sender,
 			coap_handler: coap_handler
 		}
 	}
@@ -48,37 +58,65 @@ impl<H: CoAPHandler + 'static> Handler for UdpHandler<H> {
 	type Message = ();
 
 	fn ready(&mut self, _: &mut EventLoop<UdpHandler<H>>, _: Token, events: EventSet) {
-        if events.is_readable() {
-        	let coap_handler = self.coap_handler;
-        	let mut buf = [0; 1500];
-
-			match self.socket.recv_from(&mut buf) {
-				Ok(Some((nread, src))) => {
-					self.thread_pool.execute(move || {
-						match Packet::from_bytes(&buf[..nread]) {
-							Ok(packet) => {
-								let client = CoAPClient::new(src).unwrap();
-								coap_handler.handle(packet, client);
-							},
-							Err(_) => return
-						};
-					});
-				},
-				_ => panic!("unexpected error"),
-			}
+		if !events.is_readable() {
+			warn!("Unreadable Event");
+			return;
+		}
+
+		let coap_handler = self.coap_handler;
+		let mut buf = [0; 1500];
+
+		match self.socket.recv_from(&mut buf) {
+			Ok(Some((nread, src))) => {
+				debug!("Handling request from {}", src);
+				let response_q = self.tx_sender.clone();
+				self.thread_pool.execute(move || {
+					match Packet::from_bytes(&buf[..nread]) {
+						Ok(packet) => {
+							// Pre-generate a response
+							let auto_resp = auto_response(&packet);
+							// Dispatch user handler, if there is a response packet
+							//   send the reply via the TX thread
+							match coap_handler.handle(packet, auto_resp) {
+								Some(response) => {
+									debug!("Response: {:?}", response);
+									response_q.send(CoAPResponse{
+										address: src,
+										response: response
+									}).unwrap();
+								},
+								None => {
+									debug!("No response");
+								}
+							};
+						},
+						Err(_) => {
+							error!("Failed to parse request");
+							return;
+						}
+					};
+				});
+			},
+			_ => {
+				error!("Failed to read from socket");
+				panic!("unexpected error");
+			},
 		}
+
 	}
 
 	fn notify(&mut self, event_loop: &mut EventLoop<UdpHandler<H>>, _: ()) {
-        event_loop.shutdown();
-    }
+		info!("Shutting down request handler");
+		event_loop.shutdown();
+	}
 }
 
 pub struct CoAPServer {
-    socket: UdpSocket,
-    event_sender: Option<Sender<()>>,
-    event_thread: Option<thread::JoinHandle<()>>,
-    worker_num: usize,
+	socket: UdpSocket,
+	event_sender: Option<Sender<()>>,
+	event_thread: Option<thread::JoinHandle<()>>,
+	tx_thread: Option<thread::JoinHandle<()>>,
+	worker_num: usize,
 }
 
 impl CoAPServer {
@@ -91,46 +129,66 @@ impl CoAPServer {
 						socket: s,
 						event_sender: None,
 						event_thread: None,
+						tx_thread: None,
 						worker_num: DEFAULT_WORKER_NUM,
 					}))
 				},
-				None => Err(std::io::Error::new(std::io::ErrorKind::Other, "no address"))
+				None => Err(Error::new(ErrorKind::Other, "no address"))
 			}
 		})
 	}
 
-	/// Starts handling requests with the handler.
+	/// Starts handling requests with the handler
 	pub fn handle<H: CoAPHandler + 'static>(&mut self, handler: H) -> Result<(), CoAPServerError> {
-		match self.event_sender {
-			None => {
-				let worker_num = self.worker_num;
-				let (tx, rx) = mpsc::channel();
-				let socket = self.socket.try_clone();
-				match socket {
-					Ok(socket) => {
-						let thread = thread::spawn(move || {
-							let thread_pool = ThreadPool::new(worker_num);
-							let mut event_loop = EventLoop::new().unwrap();
-							event_loop.register(&socket, Token(0), EventSet::readable(), PollOpt::edge()).unwrap();
-
-							tx.send(event_loop.channel()).unwrap();
-
-							event_loop.run(&mut UdpHandler::new(socket, thread_pool, handler)).unwrap();
-						});
-
-						match rx.recv() {
-							Ok(event_sender) => {
-								self.event_sender = Some(event_sender);
-								self.event_thread = Some(thread);
-								Ok(())
-							},
-							Err(_) => Err(CoAPServerError::EventLoopError)
-						}
-					},
-					Err(_) => Err(CoAPServerError::NetworkError),
-				}
+		let socket;
+
+		// Early return error checking
+		if let Some(_) = self.event_sender {
+			error!("Handler already running!");
+			return Err(CoAPServerError::AnotherHandlerIsRunning);
+		}
+		match self.socket.try_clone() {
+			Ok(good_socket) => {
+				socket = good_socket
+			},
+			Err(_) => {
+				error!("Network Error!");
+				return Err(CoAPServerError::NetworkError);
 			},
-			Some(_) => Err(CoAPServerError::AnotherHandlerIsRunning),
+		}
+
+		// Create resources
+		let worker_num = self.worker_num;
+		let (tx, rx) = mpsc::channel();
+		let (tx_send, tx_recv) : (TxQueue, RxQueue) = mpsc::channel();
+		let tx_only = self.socket.try_clone().unwrap();
+
+		// Setup and spawn single TX thread
+		let tx_thread = thread::spawn(move || {
+			transmit_handler(tx_recv, tx_only);
+		});
+
+		// Setup and spawn event loop thread, which will spawn
+		//   children threads which handle incomining requests
+		let thread = thread::spawn(move || {
+			let thread_pool = ThreadPool::new(worker_num);
+			let mut event_loop = EventLoop::new().unwrap();
+			event_loop.register(&socket, Token(0), EventSet::readable(), PollOpt::edge()).unwrap();
+
+			tx.send(event_loop.channel()).unwrap();
+
+			event_loop.run(&mut UdpHandler::new(socket, thread_pool, tx_send, handler)).unwrap();
+		});
+
+		// Ensure threads started successfully
+		match rx.recv() {
+			Ok(event_sender) => {
+				self.event_sender = Some(event_sender);
+				self.event_thread = Some(thread);
+				self.tx_thread = Some(tx_thread);
+				Ok(())
+			},
+			Err(_) => Err(CoAPServerError::EventLoopError)
 		}
 	}
 
@@ -152,10 +210,35 @@ impl CoAPServer {
 	}
 }
 
+fn transmit_handler(tx_recv: RxQueue, tx_only: UdpSocket) {
+	// Note! We should only transmit with this UDP Socket
+	// TODO: Add better support for failure detection or logging
+	loop {
+		match tx_recv.recv() {
+			Ok(q_res) => {
+				match q_res.response.to_bytes() {
+					Ok(bytes) => {
+						let _ = tx_only.send_to(&bytes[..], &q_res.address);
+					},
+					Err(_) => {
+						error!("Failed to decode response");
+					}
+				}
+			},
+			// recv error occurs when all transmitters are terminited
+			//   (when all UDP Handlers are closed)
+			Err(_) => {
+				info!("Shutting down Transmit Handler");
+				break;
+			}
+		}
+	}
+}
+
 impl Drop for CoAPServer {
-    fn drop(&mut self) {
-        self.stop();
-    }
+	fn drop(&mut self) {
+		self.stop();
+	}
 }
 
 
@@ -165,12 +248,17 @@ mod test {
 	use packet::{Packet, PacketType, OptionType};
 	use client::CoAPClient;
 
-	fn request_handler(req: Packet, resp: CoAPClient) {
-		let uri_path = req.get_option(OptionType::UriPath);
-		assert!(uri_path.is_some());
-		let uri_path = uri_path.unwrap();
+	fn request_handler(req: Packet, response: Option<Packet>) -> Option<Packet> {
+		let uri_path_list = req.get_option(OptionType::UriPath).unwrap();
+		assert!(uri_path_list.len() == 1);
 
-		resp.reply(&req, uri_path.front().unwrap().clone()).unwrap();
+		match response {
+			Some(mut packet) => {
+				packet.set_payload(uri_path_list.front().unwrap().clone());
+				Some(packet)
+			},
+			_ => None
+		}
 	}
 
 	#[test]