/// <summary> /// Sends a buffer. /// </summary> public bool SendAsync(IMessageSocketAsyncEventArgs args) { TcpMessageSocketAsyncEventArgs eventArgs = args as TcpMessageSocketAsyncEventArgs; if (eventArgs == null) { throw new ArgumentNullException(nameof(args)); } if (m_socket == null) { throw new InvalidOperationException("The socket is not connected."); } eventArgs.m_args.SocketError = SocketError.NotConnected; return(m_socket.SendAsync(eventArgs.m_args)); }
/// <summary> /// Connects to an endpoint. /// </summary> public async Task <bool> BeginConnect(Uri endpointUrl, EventHandler <IMessageSocketAsyncEventArgs> callback, object state) { if (endpointUrl == null) { throw new ArgumentNullException("endpointUrl"); } if (m_socket != null) { throw new InvalidOperationException("The socket is already connected."); } // Get DNS host information. IPAddress[] hostAdresses = await Dns.GetHostAddressesAsync(endpointUrl.DnsSafeHost); // try IPv4 and IPv6 address IPAddress addressV4 = null; IPAddress addressV6 = null; foreach (IPAddress address in hostAdresses) { if (address.AddressFamily == AddressFamily.InterNetworkV6) { if (addressV6 == null) { addressV6 = address; } } if (address.AddressFamily == AddressFamily.InterNetwork) { if (addressV4 == null) { addressV4 = address; } } if ((addressV4 != null) && (addressV6 != null)) { break; } } SocketError error = SocketError.NotInitialized; TaskCompletionSource <SocketError> tcs = new TaskCompletionSource <SocketError>(); TcpMessageSocketAsyncEventArgs argsV4 = null; TcpMessageSocketAsyncEventArgs argsV6 = null; m_socketResponses = 0; lock (m_socketLock) { // ensure a valid port. int port = endpointUrl.Port; if (port <= 0 || port > UInt16.MaxValue) { port = Utils.UaTcpDefaultPort; } // create sockets if IP address was provided if (addressV6 != null) { argsV6 = new TcpMessageSocketAsyncEventArgs(); argsV6.UserToken = state; m_socketV6 = new Socket(AddressFamily.InterNetworkV6, SocketType.Stream, ProtocolType.Tcp); argsV6.m_args.RemoteEndPoint = new IPEndPoint(addressV6, port); m_socketResponses++; argsV6.m_args.Completed += (o, e) => { lock (m_socketLock) { m_socketResponses--; if (m_socketV6 != null) { if (m_socket == null && (m_socketResponses == 0 || e.SocketError == SocketError.Success)) { m_socket = m_socketV6; tcs.SetResult(e.SocketError); } else { m_socketV6.Dispose(); e.UserToken = null; } m_socketV6 = null; } else { e.UserToken = null; } } }; argsV6.Completed += callback; } if (addressV4 != null) { argsV4 = new TcpMessageSocketAsyncEventArgs(); argsV4.UserToken = state; m_socketV4 = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); argsV4.m_args.RemoteEndPoint = new IPEndPoint(addressV4, port); m_socketResponses++; argsV4.m_args.Completed += (o, e) => { lock (m_socketLock) { m_socketResponses--; if (m_socketV4 != null) { if (m_socket == null && (m_socketResponses == 0 || e.SocketError == SocketError.Success)) { m_socket = m_socketV4; tcs.SetResult(e.SocketError); } else { m_socketV4.Dispose(); e.UserToken = null; } m_socketV4 = null; } else { e.UserToken = null; } } }; argsV4.Completed += callback; } bool connectV6Sync = true; bool connectV4Sync = true; if (m_socketV6 != null) { connectV6Sync = !m_socketV6.ConnectAsync(argsV6.m_args); if (connectV6Sync) { // I/O completed synchronously callback(this, argsV6); error = argsV6.m_args.SocketError; } } if (m_socketV4 != null && error != SocketError.Success) { connectV4Sync = !m_socketV4.ConnectAsync(argsV4.m_args); if (connectV4Sync) { // I/O completed synchronously callback(this, argsV4); error = argsV4.m_args.SocketError; } } if (connectV4Sync && connectV6Sync) { return((error == SocketError.Success) ? true : false); } } error = await tcs.Task; return((error == SocketError.Success) ? true : false); }
/// <summary> /// Connects to an endpoint. /// </summary> public async Task <bool> BeginConnect(Uri endpointUrl, EventHandler <IMessageSocketAsyncEventArgs> callback, object state) { if (endpointUrl == null) { throw new ArgumentNullException("endpointUrl"); } if (m_socket != null) { throw new InvalidOperationException("The socket is already connected."); } // Get DNS host information. var hostAdresses = await Dns.GetHostAddressesAsync(endpointUrl.DnsSafeHost); SocketError error = SocketError.NotInitialized; TaskCompletionSource <SocketError> tcs = new TaskCompletionSource <SocketError>(); bool allAreSyncConnected = true; TcpMessageSocketAsyncEventArgs successArgs = new TcpMessageSocketAsyncEventArgs(); TcpMessageSocketAsyncEventArgs errorArgs = new TcpMessageSocketAsyncEventArgs(); bool result; // ensure a valid port. int port = endpointUrl.Port; if (port <= 0 || port > UInt16.MaxValue) { port = Utils.UaTcpDefaultPort; } List <Socket> sockets = new List <Socket>(); foreach (var address in hostAdresses) { Socket socket = new Socket(address.AddressFamily, SocketType.Stream, ProtocolType.Tcp); TcpMessageSocketAsyncEventArgs args = new TcpMessageSocketAsyncEventArgs(); sockets.Add(socket); args.UserToken = state; args.m_args.RemoteEndPoint = new IPEndPoint(address, port); args.m_args.Completed += (o, e) => { lock (m_socketLock) { if (socket != null) { if (m_socket == null && e.SocketError == SocketError.Success) { m_socket = socket; successArgs = args; tcs.SetResult(e.SocketError); } else { socket.Dispose(); e.UserToken = null; } socket = null; } else { e.UserToken = null; } } }; if (!socket.ConnectAsync(args.m_args)) { lock (m_socketLock) { // I/O completed synchronously if (m_socket == null && args.m_args.SocketError == SocketError.Success) { successArgs = args; m_socket = socket; error = SocketError.Success; } else { if (error != SocketError.Success) { errorArgs = args; error = args.m_args.SocketError; } } } } else { allAreSyncConnected = false; } } if (!allAreSyncConnected) { error = await tcs.Task; } // dispose unused sockets for (var socketIndex = 0; socketIndex < sockets.Count; socketIndex++) { Socket socket = sockets[socketIndex]; if (socket != null && socket != m_socket) { sockets[socketIndex] = null; socket.Dispose(); } } if (error == SocketError.Success) { callback(this, successArgs); result = true; } else { callback(this, errorArgs); result = false; } return(result); }