服務端:
class Client{ TcpClient clientSocket; StreamWriter writer; public Client(TcpClient client) { clientSocket = client; NetworkStream stream = clientSocket.GetStream(); writer = new StreamWriter(stream,Encoding.ASCII); } public void write(string str) { //flush也很重要 如果你想發出去過後用戶端立即就收到請使用這個 要不他會把資料放到緩衝區裡 //用戶端也就一直在read那裡等待 writer.WriteLine(str); writer.Flush(); } public void close() { //是否調用了close 然後用戶端等待一段時間再read就會收不到資料呢 或者提示服務端已斷開異常呢 //否 只有馬上運行完後此socket不進行close 直接關閉程式。這時用戶端read操作才會報串連斷開異常 //在這之前用戶端會持續的讀到服務端發過去的資料 //注意:只要服務端先發送資料然後通過正常手續依次關閉socket、監聽 然後程式退出 //那麼用戶端也不會有問題 //看似用戶端還沒來得及收資料 //實際上write方法運行完畢這個資料就已經寫到用戶端緩衝區了(這種小資料實際上一瞬間就傳過去了) //tcp就是要保證資料已經正確到達目標機後收到一個確認後才會繼續發後面的資料的 //tcp正是通過這種機制維護了資料的完整性 //服務端正常close 那麼用戶端唯一判斷的方式就是read方法返回0 說明串連的另一端已經退出 //只要還有串連 那麼用戶端調用同步read方法那麼不讀到資料線程是會被阻塞的就一直卡在那裡 //如果寫了資料不立即Flush他也會暫時收不到資料也會卡在那裡 //如果服務端非正常關閉 則用戶端read的時候產生串連斷開異常 //基於以上所以程式兩端要"商量"著一起退出程式時通常是給對方發訊息 收到訊息後進行close writer.Close(); clientSocket.Close(); }}class Program{ static void Main(string[] args) { TcpListener server = new TcpListener(6000); server.Start(); //while (true) //{ Client c = new Client(server.AcceptTcpClient()); Console.WriteLine("新的串連"); //Thread.Sleep(2000); for (int i = 0; i < 3; i++) { c.write("hello,welcome ^_^" + i.ToString()); //Thread.Sleep(1000); } Thread.Sleep(5000); c.write("finally"); Console.WriteLine("發送完成"); Thread.Sleep(10000); c.close(); //Thread.Sleep(100000); //} server.Stop(); }}
用戶端:
class Program{ static void Main(string[] args) { TcpClient client = new TcpClient(); client.Connect(IPAddress.Parse(@"127.0.0.1"), 6000); Console.WriteLine("連上了"); StreamReader reader = new StreamReader(client.GetStream()); //Thread.Sleep(6000); while (true) { try { byte[] data = new byte[1024]; //if (client.Available > 0) //{ //read方法使用 //第三個參數不一定是client.Available 因為別人到底發了多少資料過來是未知的 //自己想對多少個位元組解碼就讀多少位元組就是了 //可能想到Read方法返回的讀取數是0 tcp是有串連的有狀態的 所以每次Read是必定能讀到東西的 //如果調用同步Read方法沒有讀到對方發過來的東西 他會掛起直到讀到資料為止 //如果調用後立即返回0說明串連已經斷開了 //Thread.Sleep(2000); int reds = reader.BaseStream.Read(data, 0, data.Length); if (reds == 0) break; if (Encoding.ASCII.GetString(data).IndexOf("finally") != -1) { Console.WriteLine(Encoding.ASCII.GetString(data, 0, reds)); break; } if (reds < data.Length) Console.WriteLine(Encoding.ASCII.GetString(data, 0, reds)); else Console.WriteLine(Encoding.ASCII.GetString(data)); //當緩衝區內沒有資料時立即就中斷讀取是不妥的 //有可能網路延遲資料還沒有發過來 //} //else // break; } catch (Exception ex) { Console.WriteLine("服務端已斷開:" + ex.Message); break; } } Console.WriteLine("over"); client.Close(); Console.ReadKey(); }}