0

wp7 エミュレーターからサーバー (同じ PC 上の Java サーバー) に udp パケットを送信し、応答を得ようとしていました。MSDN の SocketClient クラスのコードを使用しました: http://msdn.microsoft.com/en-us/library/windowsphone/develop/hh202864(v=vs.105).aspx

次の場合、完全に正常に動作します。

  1. Socketclient クラスのインスタンスを作成し、send() および receive() メソッドを呼び出すたびに。
  2. send() を使用してパケットを送信した後、いくつかの receive() を呼び出すいくつかのパケットを受信できます。

しかし、問題は-

  1. Socketclient クラスのインスタンスを作成し、send() および receive() メソッドを呼び出してから、(Socketclient クラスの同じオブジェクトから) send() および receive() を再度呼び出します。この状況では、2 回目にパケットを送信できますが、受信できません (応答「操作タイムアウト」を返します)。

再度送受信するための Socketclient クラスの新しいオブジェクトを作成すると機能しますが、プロジェクトで常に単一のソケットを使用する必要があります。これを解決するにはどうすればよいですか? ここにコードがあります-

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net.Sockets;
using System.Threading;
using System.Net;
namespace UdpClient
{
    class SocketClient
    {
        // Cached Socket object that will be used by each call for the lifetime of this class
        Socket _socket = null;
        // Signaling object used to notify when an asynchronous operation is completed
        static ManualResetEvent _clientDone = new ManualResetEvent(false);
        // Define a timeout in milliseconds for each asynchronous call. If a response is not received within this
        // timeout period, the call is aborted.
        const int TIMEOUT_MILLISECONDS = 5000;
        // The maximum size of the data buffer to use with the asynchronous socket methods
        const int MAX_BUFFER_SIZE = 2048;
        /// <summary>
        /// SocketClient Constructor
        /// </summary>
        public SocketClient()
        {
            // The following creates a socket with the following properties:
            // AddressFamily.InterNetwork - the socket will use the IP version 4 addressing scheme to resolve an address
            // SocketType.Dgram - a socket that supports datagram (message) packets
            // PrototcolType.Udp - the User Datagram Protocol (UDP)
            _socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
        }
        /// <summary>
        /// Send the given data to the server using the established connection
        /// </summary>
        /// <param name="serverName">The name of the server</param>
        /// <param name="portNumber">The number of the port over which to send the data</param>
        /// <param name="data">The data to send to the server</param>
        /// <returns>The result of the Send request</returns>
        public string Send(string serverName, int portNumber, string data)
        {
            string response = "Operation Timeout";
            // We are re-using the _socket object that was initialized in the Connect method
            if (_socket != null)
            {
                // Create SocketAsyncEventArgs context object
                SocketAsyncEventArgs socketEventArg = new SocketAsyncEventArgs();
                // Set properties on context object
                socketEventArg.RemoteEndPoint = new DnsEndPoint(serverName, portNumber);
                // Inline event handler for the Completed event.
                // Note: This event handler was implemented inline in order to make this method self-contained.
                socketEventArg.Completed += new EventHandler<SocketAsyncEventArgs>(delegate(object s, SocketAsyncEventArgs e)
                {
                    response = e.SocketError.ToString();
                    // Unblock the UI thread
                    _clientDone.Set();
                });
                // Add the data to be sent into the buffer
                byte[] payload = Encoding.UTF8.GetBytes(data);
                socketEventArg.SetBuffer(payload, 0, payload.Length);
                // Sets the state of the event to nonsignaled, causing threads to block
                _clientDone.Reset();
                // Make an asynchronous Send request over the socket
                _socket.SendToAsync(socketEventArg);
                // Block the UI thread for a maximum of TIMEOUT_MILLISECONDS milliseconds.
                // If no response comes back within this time then proceed
                _clientDone.WaitOne(TIMEOUT_MILLISECONDS);
            }
            else
            {
                response = "Socket is not initialized";
            }
            return response;
        }




        /// <summary>
        /// Receive data from the server
        /// </summary>
        /// <param name="portNumber">The port on which to receive data</param>
        /// <returns>The data received from the server</returns>
        public string Receive(int portNumber)
        {
            string response = "Operation Timeout";
            // We are receiving over an established socket connection
            if (_socket != null)
            {
                // Create SocketAsyncEventArgs context object
                SocketAsyncEventArgs socketEventArg = new SocketAsyncEventArgs();
                socketEventArg.RemoteEndPoint = new IPEndPoint(IPAddress.Any, portNumber);
                // Setup the buffer to receive the data
                socketEventArg.SetBuffer(new Byte[MAX_BUFFER_SIZE], 0, MAX_BUFFER_SIZE);
                // Inline event handler for the Completed event.
                // Note: This even handler was implemented inline in order to make this method self-contained.
                socketEventArg.Completed += new EventHandler<SocketAsyncEventArgs>(delegate(object s, SocketAsyncEventArgs e)
                {
                    if (e.SocketError == SocketError.Success)
                    {
                        // Retrieve the data from the buffer
                        response = Encoding.UTF8.GetString(e.Buffer, e.Offset, e.BytesTransferred);
                        response = response.Trim('\0');
                    }
                    else
                    {
                        response = e.SocketError.ToString();
                    }
                    _clientDone.Set();
                });
                // Sets the state of the event to nonsignaled, causing threads to block
                _clientDone.Reset();
                // Make an asynchronous Receive request over the socket
                _socket.ReceiveFromAsync(socketEventArg);
                // Block the UI thread for a maximum of TIMEOUT_MILLISECONDS milliseconds.
                // If no response comes back within this time then proceed
                _clientDone.WaitOne(TIMEOUT_MILLISECONDS);
            }
            else
            {
                response = "Socket is not initialized";
            }
            return response;
        }

        /// <summary>
        /// Closes the Socket connection and releases all associated resources
        /// </summary>
        public void Close()
        {
            if (_socket != null)
            {
                _socket.Close();
            }
        }

    }
}
4

1 に答える 1

0

問題は受信機能にありました。パケット データは文字列応答に非同期的に割り当てられましたが、receiveAsync 操作が完了する前に、現在のスレッドから変数応答が返されていました。

于 2013-10-01T08:55:59.637 に答える