簡介
聊天程式是學習網路程式設計很好的入門題目之一,在本文中,我們將示範如何用 C# 的 Socket 函式庫設計一個網路聊天程式。以下是這個程式的執行時的一個畫面,讀者可以看到我們在兩個命令列視窗中執行同一個 ChatBox 程式,左上角是 Server 程式,右下角是 Client 程式。
在上圖中,Client 可以傳送訊息給 Server ,而 Server 也可傳送訊息給 Client,由於雙方在這個傳送接收的動作上幾乎是相同的,因此在寫程式時就將這些動作封裝後共用,可以讓程式更為精簡,這就是 P2P 架構的程式。
當然,這個程式也可以放在兩台不同的電腦上執行,其結果將與上述結果類似,只是無法同時在一台電腦上看到輸入與輸出的結果而已。
原始程式碼
以下是上述雙向聊天程式 ChatBox 的原始程式碼,其中的 TcpListener 程式是 Client-Server 雙方所共用的部分,因此獨立出來變成一個類別,並且分別在 Client 與 Server 主程式當中都用 new TcpListener() 的方式呼叫。此時雙方都會建立一個寫入迴圈 (outLoop) 與讀取回圈 (inLoop),寫入迴圈不斷等待鍵盤的輸入,並在有輸入時將訊息傳遞給對方。而讀取回圈則是不斷接收對方所傳來的訊息並顯示在螢幕上。
using System;
using System.Collections.Generic;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.IO;
using System.Threading;
class ChatBox
{
int port = 20;
public static void Main(String[] args)
{
ChatBox chatBox = new ChatBox();
if (args.Length == 0)
chatBox.ServerMain();
else
chatBox.ClientMain(args[0]);
}
public void ServerMain()
{
IPEndPoint ipep = new IPEndPoint(IPAddress.Any, port);
Socket newsock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
newsock.Bind(ipep);
newsock.Listen(10);
Socket client = newsock.Accept();
new TcpListener(client); // create a new thread and then receive message.
newsock.Close();
}
public void ClientMain(String ip)
{
IPEndPoint ipep = new IPEndPoint(IPAddress.Parse(ip), port);
Socket server = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
server.Connect(ipep);
new TcpListener(server);
server.Shutdown(SocketShutdown.Both);
server.Close();
}
}
public class TcpListener
{
Socket socket;
Thread inThread, outThread;
NetworkStream stream;
StreamReader reader;
StreamWriter writer;
public TcpListener(Socket s)
{
socket = s;
stream = new NetworkStream(s);
reader = new StreamReader(stream);
writer = new StreamWriter(stream);
inThread = new Thread(new ThreadStart(inLoop));
inThread.Start();
outThread = new Thread(new ThreadStart(outLoop));
outThread.Start();
inThread.Join(); // 等待 inThread 執行續完成,才離開此函數。
// (注意、按照 inLoop 的邏輯,這個函數永遠不會跳出,因為 inLoop 是個無窮迴圈)。
}
public void inLoop()
{
while (true)
{
String line = reader.ReadLine();
Console.WriteLine("收到:" + line);
}
}
public void outLoop()
{
while (true)
{
String line = Console.ReadLine();
writer.WriteLine(line);
writer.Flush();
}
}
}
陳鍾誠 (2010年06月15日),(網頁標題) C# :雙向P2P聊天程式,(網站標題) 免費電子書:C# 程式設計,2010年06月15日,取自 http://cs0.wikidot.com/chatbox ,網頁修改第 2 版。