2

サーバーとクライアント間の接続を確立しました。クライアントはサーバーにデータを送信し、応答を受信しますが、サーバーからクライアントにデータを送信し、クライアントからサーバーへの応答を受信したいのですが、可能ですか? これが私のコードです:[クライアント]:

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

namespace Multi_Client
{
    class Program
    {
        private static Socket _clientSocket = new Socket
            (AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

        static void Main(string[] args)
        {
            Console.Title = "Client";
            ConnectToServer();
            RequestLoop();
            Exit();
        }

        private static void ConnectToServer()
        {
            int attempts = 0;

            while (!_clientSocket.Connected)
            {
                try
                {
                    attempts++;
                    Console.WriteLine("Connection attempt " + attempts);
                    _clientSocket.Connect(IPAddress.Loopback, 100);
                }
                catch (SocketException)
                {
                    Console.Clear();
                }
            }

            Console.Clear();
            Console.WriteLine("Connected");
            _clientSocket.Send(Encoding.ASCII.GetBytes("C1"));
        }

        private static void RequestLoop()
        {
            Console.WriteLine(@"<Type ""exit"" to properly disconnect client>");

            SendRequest();
            ReceiveResponse();

        }

        /// <summary>
        /// Close socket and exit app
        /// </summary>
        private static void Exit()
        {
            SendString("exit"); // Tell the server we re exiting
            _clientSocket.Shutdown(SocketShutdown.Both);
            _clientSocket.Close();
            Environment.Exit(0);
        }

        private static void SendRequest()
        {
            Console.Write("Send a request: ");
            string request = Console.ReadLine();
            SendString(request);

            if (request.ToLower() == "exit")
            {
                Exit();
                return;
            }
        }

        private static void SendString(string text)
        {
            byte[] buffer = Encoding.ASCII.GetBytes(text);
            _clientSocket.Send(buffer, 0, buffer.Length, SocketFlags.None);
        }

        private static void ReceiveResponse()
        {
            byte[] buffer = new byte[2048];
            int received = _clientSocket.Receive(buffer, SocketFlags.None);

            if (received == 0) return;

            byte[] data = new byte[received];
            Array.Copy(buffer, data, received);
            string text = Encoding.ASCII.GetString(data);
            Console.WriteLine(text);
        }
    }
}

[サーバー] :

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading;
using System.Net;
using System.IO;
using NetworkCommsDotNet;
using System.Net.Sockets;

namespace Server
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }
        private static Socket _serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
        private static List<Socket> _clientSockets = new List<Socket>();
        private static readonly int _BUFFER_SIZE = 2048;
        private static byte[] _buffer = new byte[_BUFFER_SIZE];
        string text;
        Socket current;
        Socket test;
        delegate void SetTextCallback(string text);

        private void SetText(string text)
        {
            // InvokeRequired required compares the thread ID of the
            // calling thread to the thread ID of the creating thread.
            // If these threads are different, it returns true.
            if (this.richTextBox1.InvokeRequired)
            {
                SetTextCallback d = new SetTextCallback(SetText);
                this.Invoke(d, new object[] { text });
            }
            else
            {
                this.richTextBox1.Text += text + "\n";
            }
        }
        private void SetupServer()
        {
            SetText("Setting up server...");
            _serverSocket.Bind(new IPEndPoint(IPAddress.Any, 100));
            _serverSocket.Listen(5);
            _serverSocket.BeginAccept(new AsyncCallback(AcceptCallback), null);
            SetText("Server Setup");
        }

        /// <summary>
        /// Close all connected client (we do not need to shutdown the server socket as its connections
        /// are already closed with the clients)
        /// </summary>
        private static void CloseAllSockets()
        {
            foreach (Socket socket in _clientSockets)
            {
                socket.Shutdown(SocketShutdown.Both);
                socket.Close();
            }

            _serverSocket.Close();
        }

        private void AcceptCallback(IAsyncResult AR)
        {
            Socket socket = null;

            try
            {
                socket = _serverSocket.EndAccept(AR);
            }
            catch (ObjectDisposedException) // I cannot seem to avoid this (on exit when properly closing sockets)
            {
                return;
            }

            _clientSockets.Add(socket);
            socket.BeginReceive(_buffer, 0, _BUFFER_SIZE, SocketFlags.None, new AsyncCallback(ReceiveCallback), socket);
            SetText("Client connected, waiting for request...");
            test = (Socket)AR.AsyncState;
            _serverSocket.BeginAccept(new AsyncCallback(AcceptCallback), null);
        }
        private void ReceiveCallback(IAsyncResult AR)
        {
            current = (Socket)AR.AsyncState;
            int received = 0;

            try
            {
                received = current.EndReceive(AR);
            }
            catch (SocketException)
            {
                SetText("Client forcefully disconnected");
                current.Close(); // Dont shutdown because the socket may be disposed and its disconnected anyway
                _clientSockets.Remove(current);
                return;
            }

            byte[] recBuf = new byte[received];
            Array.Copy(_buffer, recBuf, received);
            text = Encoding.ASCII.GetString(recBuf);
            SetText("Received Text: " + text);
            if (text.ToLower() == "get tim") // Client requested time
            {
                SetText("Text is a get time request");
                byte[] data = Encoding.ASCII.GetBytes(DateTime.Now.ToLongTimeString());
                current.Send(data);
                SetText("Time sent to client");
            }
            else if (text.ToString() == "C1") // Client wants to exit gracefully
            {
                SetText("Received :: C1");
                byte[] data = Encoding.ASCII.GetBytes(DateTime.Now.ToLongTimeString());
                current.Send(data);
            }

            else
            {
                SetText("Server is sending invalid packet");
                SetText("Warning Sent");
            }
            current.BeginReceive(_buffer, 0, _BUFFER_SIZE, SocketFlags.None, new AsyncCallback(ReceiveCallback), current);
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            SetupServer();
        }
        private void Send_Received(string mess)
        {
            byte[] data = Encoding.ASCII.GetBytes(mess);
            test.Send(data);
        }
        private void button2_Click(object sender, EventArgs e)
        {
            CloseAllSockets();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            Send_Received(textBox1.Text);
        }


    }
}
4

3 に答える 3

3

短い答え: はい、可能です。

長い回答: はい。現在のコードは次のように実装されています。

  • サーバーが初期化され、接続を受信する準備が整います。
  • クライアントが接続を試みます。
  • サーバーは接続を受け入れ、clientSockets コレクションに追加します。
  • クライアントは「C1」を送信します。
  • サーバーはコンテンツを受信し、解釈し、応答を返します。
  • クライアントが回答を受け取ります。

そして、他のコンテンツが送信されないため、ループに入ります。同期プロトコルを実装しました-クライアントが話し、サーバーが話し返し、クライアントがそれをコンソールにダンプします。

サーバー - >クライアント - >サーバー交換をテストできるように、簡単な実装を提案させてください。

  • サーバーに非同期タイマーを実装します。
  • 10 秒後、特定のクライアントから着信メッセージが届かない場合は、「PING?」を送信します。それへのメッセージ。
  • クライアントで受信コンテンツを解析します。メッセージが「PING?」の場合は、「PONG!」で応答します。

これは非常に単純な QoS プロトコルです。接続の状態をテストします。

実装に成功した場合はお知らせください。=)

于 2013-08-19T03:46:16.373 に答える
0

RequestLoop 関数を編集して解決しました:

private static void RequestLoop()
    {
        ReceiveResponse();

    }

それはすべてです:)

于 2013-08-24T01:58:58.137 に答える
0

実際、私は問題がどこにあるかを知っています。サーバーがクライアントに何かを送信し、クライアントがまだ何かを送信していない場合、クライアントは別のものを送信するまでそのことを表示しません:O例(複雑であることはわかっています):サーバーは C1 を送信し、コンソールに表示します C1 はクライアントに送信されます : クライアントは何もしません (コンソール C1O に表示する必要があります) クライアントは Pa (ランダム) を送信し、コンソールに表示します CAO : サーバーは Pa を受信します クライアントは Ka (ランダム) を送信し、表示しますコンソール (サーバーが Pa を受信したため、無効なリクエスト テキストを送信したため、無効なリクエスト)

于 2013-08-20T02:20:36.543 に答える