2011-02-11 182 views
5

我正在編寫一個簡單的測試程序,將字符串從客戶端發送到服務器,然後在服務器程序上顯示文本。我將如何去做這件事。從C客戶端向服務器發送字符串

這是我的客戶端代碼。

using System; 
using System.Net; 
using System.Net.Sockets; 


    class client 
    { 

     static String hostName = Dns.GetHostName(); 

     public static void Main(String[] args) 
     { 
      String test = Console.ReadLine(); 

      IPHostEntry ipEntry = Dns.GetHostByName(hostName); 
      IPAddress[] addr = ipEntry.AddressList; 

      //The first one in the array is the ip address of the hostname 
      IPAddress ipAddress = addr[0]; 


      TcpClient client = new TcpClient(); 

      //First parameter is Hostname or IP, second parameter is port on which server is listening 
      client.Connect(ipAddress, 8); 


      client.Close(); 
     } 
    } 

這裏是我的服務器代碼

using System; 
using System.Net; 
using System.Net.Sockets; 

class server 
{ 
    static int port = 8; 
    static String hostName = Dns.GetHostName(); 
    static IPAddress ipAddress; 

    public static void Main(String[] args) 
    { 
     IPHostEntry ipEntry = Dns.GetHostByName(hostName); 

     //Get a list of possible ip addresses 
     IPAddress[] addr = ipEntry.AddressList; 

     //The first one in the array is the ip address of the hostname 
     ipAddress = addr[0]; 

     TcpListener server = new TcpListener(ipAddress,port); 

     Console.Write("Listening for Connections on " + hostName + "...\n"); 

     //start listening for connections 
     server.Start(); 

     //Accept the connection from the client, you are now connected 
     Socket connection = server.AcceptSocket(); 

     Console.Write("You are now connected to the server\n\n"); 


     int pauseTime = 10000; 
     System.Threading.Thread.Sleep(pauseTime); 

     connection.Close(); 


    } 


} 

回答

8

您可以使用SendReceive重載上Socket。異步版本也存在,通過方法BeginSomething & EndSomething方法。

你發送原始字節,所以你需要決定一個協議,但很簡單。要發送一些文本,請選擇一種編碼(我將使用UTF-8)並使用Encoding.GetBytes獲取原始字節。

例子:

Byte[] bytes = Encoding.UTF8.GetBytes("Royale With Cheese"); 

UTF8是在Encoding類的靜態屬性,它的存在爲您提供方便。

然後,您可以將數據發送到服務器/客戶端:

int sent = connection.Send(bytes); 

接收:

Byte[] bytes = new Bytes[100]; 
int received = connection.Receive(bytes); 

這看起來很容易,但也有注意事項。該連接可能隨時丟失,因此您必須爲異常做好準備,特別是SocketException。同樣,如果你看看例子,你可以看到我有兩個變量sentreceived。他們持有實際發送的多少個字節SendReceive。你不能依靠套接字發送或接收所有的數據(特別是在接收時,如果對方發送的數據比預期的要少,怎麼辦?)

一種方法是循環發送,直到所有數據都被指示如發送:

var bytes = Encoding.UTF8.GetBytes("Royale With Cheese"); 
int count = 0; 
while (count < bytes.Length) // if you are brave you can do it all in the condition. 
{ 
    count += connection.Send(
     bytes, 
     count, 
     bytes.Length - count, // This can be anything as long as it doesn't overflow the buffer, bytes. 
     SocketFlags.None) 
} 

SendReceive是同步的,他們阻止,直到他們已經送東西。您應該在套接字上設置某種超時值(Socket.SendTimeout & Socket.ReceiveTimeout。)默認值爲0,這意味着它們可能永遠阻塞。

現在如何接收?讓我們試着做一個類似的循環。

int count = 0; 
var bytes = new Byte[100]; 
do 
{ 
    count += connection.Receive(
     bytes, 
     count, 
     bytes.Length - count, 
     SocketFlags.None); 
} while (count < bytes.Length); 

嗯。那麼......如果客戶發送少於100個,會發生什麼?我們會阻塞,直到它達到超時,如果有,或客戶端發送足夠的數據。如果客戶發送超過100個,會發生什麼?你只會得到100個第一個字節。

在你的情況下,我們可以嘗試讀取非常少量並打印。閱讀,打印,循環:

var sunIsBurning = true; 
while (sunIsBurning) { 
    var bytes = new Byte[16]; 
    int received = socket.Receive(bytes); 
    if (received > 0) 
     Console.Out.WriteLine("Got {0} bytes. START:{1}END;", received, Encoding.UTF8.GetString(bytes)); 
} 

在這裏,我們說 「只要sunIsBurning,解碼爲UTF-8接收16個字節的塊數據」。這意味着對方發送的數據必須是UTF-8,否則您將得到一個異常(它可能會被您捕獲)。這也意味着服務器只會在連接失敗時停止接收。

如果您收到了15個字節,並且客戶端終止了連接,那麼這15個字節將永遠不會被打印。您將需要更好的錯誤處理:)

在大多數情況下,未捕獲的異常將會終止您的應用程序;不適合服務器。

「連接失敗」可能意味着a lot of things,可能是由對等設備重置了連接或者您的網卡着火了。

相關問題