簡體   English   中英

C# .Net 套接字服務器客戶端

[英]C# .Net Socket Server Client

我對 C# 中的 .Net 套接字有一點問題。 我編寫了一個使用 TCP 的客戶端和一個服務器。

當客戶端打開時,它會向服務器發送握手。 服務器用它的狀態(clientexists,clientaccepted,...)回答。 之后,應用程序發送一個 getdata 請求,放棄連接並偵聽服務器的“響應”。 現在,服務器建立到客戶端的連接並發送客戶端需要的所有數據。

代碼和其他一切都有效,但問題是:

在我們公司的測試服務器上它工作正常,在實時服務器上只有握手工作。 之后,客戶端不再接收任何數據。 服務器應用程序在兩台服務器上是相同的。

我認為問題是由某些防火牆引起的(服務器想要與客戶端建立 tcp 連接 -> 不好),但系統管理員說沒有防火牆可以阻止它。

現在我正在尋找一種(“便宜”)解決方案,它不會花費太多時間和代碼更改。 如果有人知道如何從理論上解決這個問題,那就太好了。

順便說一句:除了運行服務器應用程序之外,我不允許在實時服務器上做任何事情。 我無法在此服務器上進行調試。

我無法發布我的所有代碼,但如果您需要查看其中的特定部分,請索取。

- -編輯 - -

客戶端-服務器通信

1) 客戶端啟動
客戶端發送握手(新的 tcp 連接)
2)服務器驗證握手並保存IP
服務器以其客戶端狀態響應(相同的 tcp 連接)
3) 客戶端確認此響應並放棄此連接
客戶端發送 getdata-request(新的 tcp 連接)
客戶端也放棄了這個 tcp 連接
4)服務器接收getdata-request,在主庫中收集需要的數據
服務器將所有收集到的數據發送給客戶端(多個 tcp 連接)
5) 客戶端接收所有數據並將其顯示在它的 GUI 中(多個 tcp 連接和數據的順序通過使用 AutoResetEvents 和要發送的套接字計數來保持)

這是我的代碼所做的主要部分。 到目前為止,它不是最好的,但我猜它是為我寫的。 第一步、第二步和第三步按預期工作。 數據的處理也很好。 我忘記提及的另一件事是該解決方案使用兩個端口“16777”和“16778”。 一個接收/收聽,一個發送。 我的代碼基於異步服務器客戶端的 MSDN 示例。

發送握手(和 getdata-request)

    public void BeginSend(String data)
    {
        try
        {
            StateObject state = new StateObject();
            state.workSocket = sender;

            byte[] byteData = Encoding.UTF8.GetBytes(data);

            sender.BeginSend(byteData, 0, byteData.Length, 0,
                new AsyncCallback((IAsyncResult e) =>
                {
                    Socket socket = (Socket)e.AsyncState;
                    SocketBase.StateObject stateObject = new SocketBase.StateObject();
                    stateObject.workSocket = socket;
                    socket.BeginReceive(stateObject.buffer, 0, 256, SocketFlags.None, new AsyncCallback(this.ReadCallback), (object)stateObject);

                }), sender);

            sender = RetrieveSocket(); //Socketreset

            Thread.Sleep(100);
        }
        catch /*(Exception e)*/
        {
            //--
        }
    }

服務器偵聽器

    public void StartListening()
    {
        listener = new Socket(AddressFamily.InterNetwork,
            SocketType.Stream, ProtocolType.Tcp);

        // Bind the socket to the local endpoint and listen for incoming connections.
        try
        {
            listener.Bind(localEndPoint);
            listener.Listen(System.Int32.MaxValue);

            while (true)
            {
                // Set the event to nonsignaled state.
                allDone.Reset();

                // Start an asynchronous socket to listen for connections.
                listener.BeginAccept(
                    new AsyncCallback(AcceptCallback),
                    listener);

                // Wait until a connection is made before continuing.
                allDone.WaitOne();
            }

        }
        catch (Exception e)
        {
             //--
        }
    }

    public void AcceptCallback(...);
    public void ReadCallback(...);

套接字發送

    private void Send(Socket handler, String data)
    {
        Socket t = RetrieveSocket(((IPEndPoint)handler.RemoteEndPoint).Address);
        // Convert the string data to byte data using ASCII encoding.
        byte[] byteData = Encoding.UTF8.GetBytes(data);

        // Begin sending the data to the remote device.
        t.BeginSend(byteData, 0, byteData.Length, 0,
            new AsyncCallback(SendCallback), t);
    }

Socket發送所有數據部分(getdata-request | socToHandle的回答應該是getdata-request的前一個連接的socket)

    private void SendAllData(Socket socToHandle, string PakContent)
    {
        #region IsThereADatetime? //Resolve a given datetime

        #region GiveClientNumberOfPackets //Send the client info about how much he has to receive (See line below)

            Send(socToHandle, "ALERT#TASKCOUNT;OPT-" + GetBestDate(dateStart) + EndSocket); 


        #region #SendResouces
        #region #SendGroups
        #region #SendTasks
    }

查看我的舊代碼,我有一個想法 =>

我可以通過更改通過同一連接發送所有內容:

Socket t = RetrieveSocket(((IPEndPoint)handler.RemoteEndPoint).Address);

(創建一個新連接)到使用相同連接的東西? 如果那行得通,我該怎么做? 客戶端的偵聽器部分還會收到單個數據包嗎?

服務器及其環境配置為正確處理傳入請求。 客戶端通常位於路由器后面,默認情況下,這使它們無法接收來自網絡外部的傳入連接(一件好事)。

要啟用傳入連接,您可以將路由器配置為將特定端口號的所有請求轉發到您的機器。 但是,您網絡上的其他人將無法運行客戶端。

這就是為什么在典型的多客戶端-單服務器環境中,客戶端進行所有連接,並且只有服務器需要對網絡格局進行任何更改。

我不知道你為什么選擇從服務器端連接到客戶端,但我強烈建議不要這樣做 - 任何使用這種機制的廉價解決方案最終可能會變得非常昂貴。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM