瀏覽代碼

Improve TCPSocket

Daniele Bartolini 12 年之前
父節點
當前提交
2cd87b69c3
共有 1 個文件被更改,包括 83 次插入27 次删除
  1. 83 27
      engine/os/posix/OsSocket.h

+ 83 - 27
engine/os/posix/OsSocket.h

@@ -42,13 +42,13 @@ namespace crown
 
 struct ReadResult
 {
-	enum { NO_RESULT_ERROR, UNKNOWN, REMOTE_CLOSED } error;
+	enum { NO_ERROR, UNKNOWN, REMOTE_CLOSED } error;
 	size_t received_bytes;
 };
 
 struct WriteResult
 {
-	enum { NO_RESULT_ERROR, UNKNOWN, REMOTE_CLOSED } error;
+	enum { NO_ERROR, UNKNOWN, REMOTE_CLOSED } error;
 	size_t sent_bytes;
 };
 
@@ -96,8 +96,6 @@ public:
 			return false;
 		}
 
-		fcntl(sock_id, F_SETFL, O_NONBLOCK);
-
 		return true;
 	}
 
@@ -112,51 +110,110 @@ public:
 	}
 
 	//-----------------------------------------------------------------------------
-	ReadResult read(void* data, size_t size)
+	ReadResult read_nonblock(void* data, size_t size)
 	{
-		CE_ASSERT_NOT_NULL(data);
-
-		ssize_t received_bytes = ::read(m_socket, (char*) data, size);
+		fcntl(m_socket, F_SETFL, O_NONBLOCK);
+		ssize_t read_bytes = ::read(m_socket, (char*) data, size);
 
 		ReadResult result;
-
-		if (received_bytes == -1 && errno == EAGAIN)
+		if (read_bytes == -1 && (errno == EAGAIN || errno == EWOULDBLOCK))
 		{
-			result.error = ReadResult::NO_RESULT_ERROR;
+			result.error = ReadResult::NO_ERROR;
 			result.received_bytes = 0;
 		}
-		else if (received_bytes == 0)
+		else if (read_bytes == 0)
 		{
 			result.error = ReadResult::REMOTE_CLOSED;
 		}
 		else
 		{
-			result.error = ReadResult::NO_RESULT_ERROR;
-			result.received_bytes = received_bytes;
+			result.error = ReadResult::NO_ERROR;
+			result.received_bytes = read_bytes;
 		}
 
-		return result;
+		return result;		
 	}
 
 	//-----------------------------------------------------------------------------
-	WriteResult write(const void* data, size_t size)
+	ReadResult read(void* data, size_t size)
 	{
 		CE_ASSERT_NOT_NULL(data);
 
-		ssize_t sent_bytes = ::send(m_socket, (const char*) data, size, 0);
+		int flags = fcntl(m_socket, F_GETFL, 0);
+		fcntl(m_socket, F_SETFL, flags & ~O_NONBLOCK);
 
-		WriteResult result;
+		// Ensure all data is read
+		char* buf = (char*) data;
+		size_t to_read = size;
+		ReadResult result;
+		result.received_bytes = 0;
+		result.error = ReadResult::NO_ERROR;
 
-		if (sent_bytes == -1)
+		while (to_read > 0)
 		{
-			result.error = WriteResult::UNKNOWN;
+			ssize_t read_bytes = ::read(m_socket, buf, to_read);
+			
+			if (read_bytes == -1 && (errno == EAGAIN || errno == EWOULDBLOCK)) continue;
+			else if (read_bytes == 0)
+			{
+				result.error = ReadResult::REMOTE_CLOSED;
+				return result;
+			}
+
+			buf += read_bytes;
+			to_read -= read_bytes;
+			result.received_bytes += read_bytes;
 		}
-		else
+
+		result.error = ReadResult::NO_ERROR;
+		return result;
+	}
+
+	//-----------------------------------------------------------------------------
+	WriteResult write_nonblock(const void* data, size_t size)
+	{
+		CE_ASSERT_NOT_NULL(data);
+	}
+
+	//-----------------------------------------------------------------------------
+	WriteResult write(const void* data, size_t size)
+	{
+		CE_ASSERT_NOT_NULL(data);
+
+		const char* buf = (const char*) data;
+		size_t to_send = size;
+		WriteResult result;
+		result.sent_bytes = 0;
+		result.error = WriteResult::NO_ERROR;
+
+		// Ensure all data is sent
+		while (to_send > 0)
 		{
-			result.error = WriteResult::NO_RESULT_ERROR;
-			result.sent_bytes = sent_bytes;
+			ssize_t sent_bytes = ::send(m_socket, (const char*) buf, to_send, 0);
+
+			// Check for errors
+			if (sent_bytes == -1)
+			{
+				switch (errno)
+				{
+					case EAGAIN:
+					{
+						continue;
+					}
+					default:
+					{
+						result.error = WriteResult::UNKNOWN;
+						return result;
+					}
+				}
+			}
+
+			buf += sent_bytes;
+			to_send -= sent_bytes;
+			result.sent_bytes += sent_bytes;
 		}
 
+		result.error = WriteResult::NO_ERROR;
 		return result;
 	}
 
@@ -215,7 +272,6 @@ public:
 			return false;
 		}
 
-		fcntl(asd, F_SETFL, O_NONBLOCK);
 		c.m_socket = asd;
 
 		return true;
@@ -312,7 +368,7 @@ public:
 
 		if (received_bytes == -1 && errno == EAGAIN)
 		{
-			result.error = ReadResult::NO_RESULT_ERROR;
+			result.error = ReadResult::NO_ERROR;
 			result.received_bytes = 0;
 		}
 		else if (received_bytes == 0)
@@ -321,7 +377,7 @@ public:
 		}
 		else
 		{
-			result.error = ReadResult::NO_RESULT_ERROR;
+			result.error = ReadResult::NO_ERROR;
 			result.received_bytes = received_bytes;
 		}
 
@@ -351,7 +407,7 @@ public:
 			return result;
 		}
 
-		result.error = WriteResult::NO_RESULT_ERROR;
+		result.error = WriteResult::NO_ERROR;
 		result.sent_bytes = sent_bytes;
 		return result;
 	}