1. 程式人生 > >C#Socket教程詳解一:同步TCP程式設計

C#Socket教程詳解一:同步TCP程式設計

服務端重要類:

TcpListener類,伺服器監聽類,用於監聽和連線客戶端,該類重要方法如下:

構造方法:

public TcpListener(IPEndPoint iep);

public TcpListener(IPAddress localAddress,int port);

第一個建構函式是使用IPEndPont物件初始化TcpListener類。

第二個建構函式是直接指定伺服器監聽地址和埠。

Start方法,用於啟動伺服器監聽,該方法具有倆個過載。

public void Start();

public void Start(int num);

第一個直接啟動伺服器監聽,第二個是指定能連入伺服器的最大客戶端數目。

Stop方法,用於伺服器停止監聽。

public void Stop();

AcceptSocket和AccpetTcpClient方法。都是用於獲取並返回一個物件,用於向客戶端傳送或接收訊息。

public Socket AcceptSocket();獲取並返回一個socket物件

public TcpClient AcceptTcpClient();獲取並返回一個TcpClient物件

服務端程式碼:

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace Server
{
    class MyServer
    {
        static void Main(string[] args)
        {
            //指定地址
            IPAddress ipAddress = IPAddress.Parse("192.168.0.200");
            //指定埠
            int port = 50000;      
            //宣告一個伺服器監聽物件
            TcpListener tcpListener;
            //用指定的地址埠初始化該物件
            tcpListener = new TcpListener(ipAddress, port);

            try
            {             
                Console.WriteLine("伺服器啟動中...");
                //啟動伺服器監聽物件
                tcpListener.Start();
            }
            catch(SocketException e) //處理啟動失敗異常
            {
                //列印異常
                Console.WriteLine("出現錯誤,請檢查伺服器套接字是否可用!");
                Console.WriteLine("原因:" + e);
                //暫停2s後,結束程式
                Thread.Sleep(2000);
                System.Environment.Exit(System.Environment.ExitCode);
            }

            Console.WriteLine("伺服器啟動成功");
            Console.WriteLine("等待客戶端連入中...");

            //開啟一個迴圈,用於接受連入的客戶端
            while(true)
            {
                try
                {
                    //宣告一個TcpClient物件,並接受通過連入的客戶端初始化它。
                    TcpClient tcpClient = tcpListener.AcceptTcpClient();

                    //列印連入的客戶端地址埠
                    Console.WriteLine("客戶端:"+tcpClient.Client.RemoteEndPoint+"連入伺服器!");

                    //開啟一個可傳遞引數的執行緒
                    Thread thread = new Thread(new ParameterizedThreadStart(Client));

                    //將獲取的TcpClient物件傳遞到執行緒,並啟動執行緒。
                    thread.Start(tcpClient);
                }
                catch
                {
                    //處理異常代買
                }
            }
        }


        /// <summary>
        /// 用於接受客戶端請求,並回應客戶端
        /// </summary>
        /// <param name="tcpClient"></param>
        private static void Client(object tcpClient)
        {
            //宣告一個TcpClient物件,用於獲取執行緒傳入的引數。
            TcpClient client = (TcpClient)tcpClient;
            //得到NetWorkStream物件
            NetworkStream ns = client.GetStream();

            //獲取BinaryReader物件,用於接受客戶端資訊
            BinaryReader br = new BinaryReader(ns);

            //獲取BinaWriter物件,用於迴應客戶端訊息
            BinaryWriter bw = new BinaryWriter(ns);

            //接受客戶端請求。並列印。
            string st1 = br.ReadString().ToString();
            Console.WriteLine("客戶端" + client.Client.RemoteEndPoint + "發來請求:" + st1);
            //迴應客戶端請求
            bw.Write("抱歉,我沒有蘋果。");
            Console.WriteLine("伺服器迴應:抱歉,我沒有蘋果。");


            //為了簡明,這裡只進行了一次收發訊息,實際應用中應當可以進行多次收發,直到一方斷開連線
            
        }

    }
}

客戶端端重要類:

TcpClient類,用於連線伺服器。

它有4個構造方法。我們這裡使用預設構造方法:

public TcpClient();

Connect有3個過載方法,我們也只介紹一個。

public void Connect(IPAddress ip,int port);用指定地址IP連線伺服器。

GetStream方法

public NetworkStream GetStream();用於獲取NetworkStream物件來收發資訊

其他一些沒寫出來的方法,可以評論問我

客戶端程式碼:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Net;
using System.Net.Sockets;
using System.IO;

namespace Client
{
    class Program
    {
        static void Main(string[] args)
        {
            //指定埠和地址
            IPAddress ip = IPAddress.Parse("192.168.0.200");
            int point = 50000;
            IPEndPoint ipEndPoint = new IPEndPoint(ip, point);

            //宣告並初始化一個TcpClient物件,用於連線伺服器。
            TcpClient client = new TcpClient();

            try
            {
                Console.WriteLine("客戶端請求連線伺服器");

                //用指定地址埠連線伺服器
                client.Connect(ipEndPoint);
                Console.WriteLine("客戶端連線伺服器成功");
            }
            catch
            {
                //處理連線失敗的異常
            }

            //得到用於收發資訊的物件
            NetworkStream ns = client.GetStream();
            BinaryReader br = new BinaryReader(ns);
            BinaryWriter bw = new BinaryWriter(ns);

            //傳送並打印發送的資訊
            bw.Write("我想要一個蘋果");
            Console.WriteLine("客戶端傳送請求:我想要一個蘋果");

            //接受並列印接受到的資訊
            Console.WriteLine("伺服器迴應:" + br.ReadString());

            
            Console.ReadLine();
        }
    }
}

執行結果:

注意事項:

編寫服務端時,伺服器指定的地址應為本地地址(使用公網IP會報錯),埠注意必須是沒有被佔用的埠。

編寫客戶端時,如果客戶端和伺服器在同一臺機器上,客戶端可以使用本地地址。如果不在同一臺機器上,客戶端必須使用伺服器的遠端公網IP。

下一篇將講解TCP非同步程式設計。