C# : 雙向的P2P聊天程式

作品

書籍

課程

程式集

小說集

論文集

散文集

影片集

編輯雜誌

程式人

電子書

JavaScript

計算語言學

微積分

Blender 動畫

C# 語言

系統程式

高等 C 語言

Java

Android

Verilog

Wikidot

R 統計軟體

機率統計

計算機數學

組合語言

人工智慧

開放原始碼

網路資源運用

計算機結構

相關訊息

常用工具

友站連結

在家教育

RSS

最新修改

網頁列表

簡體版

English

簡介

聊天程式是學習網路程式設計很好的入門題目之一,在本文中,我們將示範如何用 C# 的 Socket 函式庫設計一個網路聊天程式。以下是這個程式的執行時的一個畫面,讀者可以看到我們在兩個命令列視窗中執行同一個 ChatBox 程式,左上角是 Server 程式,右下角是 Client 程式。

ChatBox.jpg

在上圖中,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();
        }
    }
}

Facebook

Unless otherwise stated, the content of this page is licensed under Creative Commons Attribution-NonCommercial-ShareAlike 3.0 License