2016-10-22 25 views
5

我创建了一个.NET的核心Unix套接字在Linux(Ubuntu的16.04):如何连接到Unix域套接字在.NET的核心在C#

var unixSocket = "/var/run/mysqld/mysqld.sock"; 
var socket = new Socket(AddressFamily.Unix, SocketType.Stream, ProtocolType.IP); 

现在我该怎样连接插座?

的.NET核心API列出了各种Socket.Connect选项,但所有除了第一个处理IP地址:

public void Connect(EndPoint remoteEP) 
public void Connect(IPAddress address, int port) 
public void Connect(IPAddress[] addresses, int port) 
public void Connect(string host, int port) 

System.Net API定义DNSEndpointIPEndpoint,但我似乎无法找到一个UnixEndpoint或同级传递给Socket.Connect(EndPoint remoteEP)

+0

@PeterDuniho我使用。在Linux上的NET核心(更新我的问题,以反映这一点)。当然有一种方法可以让POSIX调用打开一个unix域套接字?请不要将此标记为重复项,标记的副本与此问题无关。 – Caleb

回答

4

似乎没有成为一个内置UnixEndPoint类.NET的核心或实现一个在写这篇文章时库。该项目UnixEndPoint class from the Mono.Posix可以很容易地适应然而,随着.NET的核心工作,:

// copied from https://github.com/mono/mono/blob/master/mcs/class/Mono.Posix/Mono.Unix/UnixEndPoint.cs 

// 
// Mono.Unix.UnixEndPoint: EndPoint derived class for AF_UNIX family sockets. 
// 
// Authors: 
// Gonzalo Paniagua Javier ([email protected]) 
// 
// (C) 2003 Ximian, Inc (http://www.ximian.com) 
// 

// 
// Permission is hereby granted, free of charge, to any person obtaining 
// a copy of this software and associated documentation files (the 
// "Software"), to deal in the Software without restriction, including 
// without limitation the rights to use, copy, modify, merge, publish, 
// distribute, sublicense, and/or sell copies of the Software, and to 
// permit persons to whom the Software is furnished to do so, subject to 
// the following conditions: 
// 
// The above copyright notice and this permission notice shall be 
// included in all copies or substantial portions of the Software. 
// 
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 
// 

using System.Net.Sockets; 
using System.Text; 

namespace System.Net 
{ 

    public class UnixEndPoint : EndPoint 
    { 
     string filename; 

     public UnixEndPoint (string filename) 
     { 
      if (filename == null) 
       throw new ArgumentNullException ("filename"); 

      if (filename == "") 
       throw new ArgumentException ("Cannot be empty.", "filename"); 
      this.filename = filename; 
     } 

     public string Filename { 
      get { 
       return(filename); 
      } 
      set { 
       filename=value; 
      } 
     } 

     public override AddressFamily AddressFamily { 
      get { return AddressFamily.Unix; } 
     } 

     public override EndPoint Create (SocketAddress socketAddress) 
     { 
      /* 
      * Should also check this 
      * 
      int addr = (int) AddressFamily.Unix; 
      if (socketAddress [0] != (addr & 0xFF)) 
       throw new ArgumentException ("socketAddress is not a unix socket address."); 
      if (socketAddress [1] != ((addr & 0xFF00) >> 8)) 
       throw new ArgumentException ("socketAddress is not a unix socket address."); 
      */ 

      if (socketAddress.Size == 2) { 
       // Empty filename. 
       // Probably from RemoteEndPoint which on linux does not return the file name. 
       UnixEndPoint uep = new UnixEndPoint ("a"); 
       uep.filename = ""; 
       return uep; 
      } 
      int size = socketAddress.Size - 2; 
      byte [] bytes = new byte [size]; 
      for (int i = 0; i < bytes.Length; i++) { 
       bytes [i] = socketAddress [i + 2]; 
       // There may be junk after the null terminator, so ignore it all. 
       if (bytes [i] == 0) { 
        size = i; 
        break; 
       } 
      } 

      string name = Encoding.UTF8.GetString (bytes, 0, size); 
      return new UnixEndPoint (name); 
     } 

     public override SocketAddress Serialize() 
     { 
      byte [] bytes = Encoding.UTF8.GetBytes (filename); 
      SocketAddress sa = new SocketAddress (AddressFamily, 2 + bytes.Length + 1); 
      // sa [0] -> family low byte, sa [1] -> family high byte 
      for (int i = 0; i < bytes.Length; i++) 
       sa [2 + i] = bytes [i]; 

      //NULL suffix for non-abstract path 
      sa[2 + bytes.Length] = 0; 

      return sa; 
     } 

     public override string ToString() { 
      return(filename); 
     } 

     public override int GetHashCode() 
     { 
      return filename.GetHashCode(); 
     } 

     public override bool Equals (object o) 
     { 
      UnixEndPoint other = o as UnixEndPoint; 
      if (other == null) 
       return false; 

      return (other.filename == filename); 
     } 
    } 
} 

有了这个类在你的项目中,插座可以连接像这样:

var unixSocket = "/var/run/mysqld/mysqld.sock"; 
var socket = new Socket(AddressFamily.Unix, SocketType.Stream, ProtocolType.IP); 
var unixEp = new UnixEndPoint(unixSocket); 
socket.Connect(unixEp);