您好我有一个使用openssl和winapi套接字的c应用程序,代码如下所示:
sock = socket(AF_INET,SOCK_STREAM,0); if (connect(my_sock,(struct sockaddr*)&dest_addr,sizeof(dest_addr))==0) { WSAIoctl(my_sock,SIO_KEEPALIVE_VALS,&alive,sizeof(alive),NULL,&dwSize,NULL); } } ..... SSL_load_error_strings(); SSL_library_init(); ctx = SSL_CTX_new(SSLv23_client_method()); if(!ctx) { return false; } ssl = SSL_new(ctx); SSL_CTX_free(ctx); if(!ssl) { return false; } SSL_set_fd(ssl,(int)sock); //making the socket use ssl mode result = SSL_connect(ssl);
我使用静态ssl库与此c应用程序,我从here下载
一切正常,ssl_connect返回1.但我需要做的是使用c#重写这段代码.所以我试过,c#代码看起来像这样:
[DllImport("ssleay32.dll",CallingConvention = CallingConvention.Cdecl,EntryPoint = "SSL_read")] public static extern int SSL_Read(IntPtr ssl,ref byte[] buf,int num); [DllImport("ssleay32.dll",EntryPoint = "SSL_write")] public static extern int SSL_Write(IntPtr ssl,byte[] buf,EntryPoint = "SSL_set_fd")] extern public static int SSL_set_fd(IntPtr ssl,int fd); [DllImport("ssleay32.dll",CallingConvention= CallingConvention.Cdecl,EntryPoint = "SSL_CTX_new")] extern public static IntPtr SSL_CTX_new(IntPtr method); [DllImport("ssleay32.dll",EntryPoint = "SSL_new")] extern public static IntPtr SSL_new(IntPtr ctx); [DllImport("ssleay32.dll",EntryPoint = "SSL_connect")] extern public static int SSL_connect(IntPtr ssl); [DllImport("ssleay32.dll",EntryPoint = "SSL_load_error_strings")] extern public static void SSL_load_error_strings(); [DllImport("ssleay32.dll",EntryPoint = "SSL_library_init")] extern public static int SSL_library_init(); [DllImport("ssleay32.dll",EntryPoint = "SSLeay_add_all_algorithms")] extern public static int SSLeay_add_all_algorithms(); [DllImport("ssleay32.dll",EntryPoint = "SSLv23_client_method")] extern public static IntPtr SSLv23_client_method(); [DllImport("ssleay32.dll",EntryPoint = "SSLv3_client_method")] extern public static IntPtr SSLv3_client_method(); [DllImport("ssleay32.dll",EntryPoint = "SSL_CTX_free")] extern public static void SSL_CTX_free(IntPtr ctx); [DllImport("ssleay32.dll",EntryPoint = "SSL_free")] extern public static void SSL_free(IntPtr ssl); [DllImport("ssleay32.dll",EntryPoint = "SSL_get_error")] extern public static int SSL_get_error(IntPtr ssl,int ret); [DllImport("ssleay32.dll",EntryPoint = " SSL_CTX_set_mode")] extern public static long SSL_CTX_set_mode(IntPtr ctx,long mode); [DllImport("libeay32",EntryPoint = "OPENSSL_add_all_algorithms_noconf")] extern public static void OpenSSL_add_all_algorithms(); [DllImport("libeay32",EntryPoint = "ERR_get_error")] extern public static int ERR_get_error(); [DllImport("ssleay32.dll",EntryPoint = "SSL_CTX_ctrl")] public extern static int SSL_CTX_ctrl(IntPtr ctx,int cmd,int arg,IntPtr parg); [DllImport("ssleay32.dll",EntryPoint = "SSLv23_method")] public extern static IntPtr SSLv23_method(); public bool Ssl_Init() { SSL_load_error_strings(); OpenSSL_add_all_algorithms(); SSL_library_init(); IntPtr method = SSLv23_client_method(); IntPtr ctx = SSL_CTX_new(method); if (ctx == IntPtr.Zero) { return false; } _ssl = SSL_new(ctx); if (_ssl == IntPtr.Zero) { return false; } int val = SSL_set_fd(_ssl,this.socket.Handle.ToInt32()); //always returns 1 int result = SSL_connect(_ssl); if(result!=1) return false; SSL_CTX_free(ctx); Ssl_Enabled.Set(); return true; }
我的c#socket是这样创建的:
socket = new Socket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp); this.socket.Connect(host,port); socket.SetSocketOption(SocketOptionLevel.Socket,SocketOptionName.KeepAlive,1000);
我总是在我的c#代码中获得SSL_Connect = 0,其中SSL_get_error()= 5(error_syscall).所以基本上我的问题是,使用.net socket和openssl可能有什么问题? (因为c应用程序与相同类型的代码完美配合).
更新:我尝试使用OPENSSL_add_all_algorithms_conf,但它似乎没有改变任何东西……我求求你的帮助!!
解决方法
据我所知,System.Net.Sockets类不支持SSL.经过一些研究,它看起来像是在System.Net.Security和System.Security.Authentication中……
这是MS示例的链接……
http://msdn.microsoft.com/en-us/library/system.net.security.sslstream(v=vs.110).aspx
此示例将一条消息发送到服务器,然后断开连接.我写了一个类似的(非SSL)客户端,它是全双工(发送和接收异步).您可以使用某些MS示例调整我的示例以通过SSL进行通信.
这是……希望它有所帮助……如果你让它适应SSL,请告诉我,因为我可能需要这样做.
using System; using System.Text; using System.Net.Sockets; using System.Collections.Generic; namespace MyNamespace.Utilities { public class StateObject{ public Socket workSocket = null; public const int BUFFER_SIZE = 1024; public byte[] buffer = new byte[BUFFER_SIZE]; //public StringBuilder message = new StringBuilder(); } public class FullDuplexSocket : IDisposable { public event NewMessageHandler OnMessageReceived; public delegate void NewMessageHandler(string Message); public event DisconnectHandler OnDisconnect; public delegate void DisconnectHandler(string Reason); private Socket _socket; private bool _useASCII = true; private string _remoteServerIp = ""; private int _port = 0; private bool _allowRetry = true; /// <summary> /// Constructer of a full duplex client socket. The consumer should immedately define /// and event handler for the OnMessageReceived event after construction has completed. /// </summary> /// <param name="RemoteServerIp">The remote Ip address of the server.</param> /// <param name="Port">The port that will used to transfer/receive messages to/from the remote IP.</param> /// <param name="UseASCII">The character type to encode/decode messages. Defaulted to use ASCII,but setting the value to false will encode/decode messages in UNICODE.</param> public FullDuplexSocket(string RemoteServerIp,int Port,bool UseASCII = true) { _useASCII = UseASCII; _remoteServerIp = RemoteServerIp; _port = Port; Initialize(); } private void Initialize() { try //to create the socket and connect { _socket = new Socket(AddressFamily.InterNetwork,ProtocolType.Tcp); _socket.Connect(_remoteServerIp,_port); } catch (Exception e) { throw new Exception("Unable to connect to the remote Ip.",e); } try //to listen to the socket { StateObject stateObject = new StateObject(); stateObject.workSocket = _socket; _socket.BeginReceive ( stateObject.buffer,//Buffer to load in our state object 0,//Start at the first position in the byte array StateObject.BUFFER_SIZE,//only load up to the max per read 0,//Set socket flags here if necessary new AsyncCallback(ReadFromSocket),//Who to call when data arrives stateObject //state object to use when data arrives ); _allowRetry = true; } catch (Exception e) { throw new Exception("Unable to start listening to the socket.",e); } } /// <summary> /// This will read the bytes from the socket,convert the bytes to a string and fire the OnMessageReceived event. /// If the socket is forcibly closed,the OnDisconnect event will be fired. This happens when the other side of /// the socket connection on the remote Ip is no longer available. /// </summary> /// <param name="asyncResult"></param> public void ReadFromSocket(IAsyncResult asyncResult) { StateObject stateObject = (StateObject)asyncResult.AsyncState; //pull out the state object int bytesReceived = 0; try //to receive the message. { bytesReceived = stateObject.workSocket.EndReceive(asyncResult); } catch (Exception e) //Exception will occur if connection was forcibly closed. { RaiseOnDisconnect(e.Message); return; } if (bytesReceived > 0) { RaiseOnMessageReceived ( _useASCII ? Encoding.ASCII.GetString(stateObject.buffer,bytesReceived) : Encoding.Unicode.GetString(stateObject.buffer,bytesReceived) ); try //The BeginRecieve can file due to network issues. _allowRetry allows a single failure between successful connections. { if (_allowRetry) { stateObject.workSocket.BeginReceive ( stateObject.buffer,//Buffer to load in our state object 0,//Start at the first position in the byte array StateObject.BUFFER_SIZE,//only load up to the max per read 0,//Set socket flags here if necessary new AsyncCallback(ReadFromSocket),//Who to call when data arrives stateObject //state object to use when data arrives ); } } catch { _allowRetry = false; } } else { stateObject.workSocket.Close(); RaiseOnDisconnect("Socket closed normally."); return; } } /// <summary> /// Broadcast a message to the IP/Port. Consumer should handle any exceptions thrown by the socket. /// </summary> /// <param name="Message">The message to be sent will be encoded using the character set defined during construction.</param> public void Send(string Message) { //all messages are terminated with /r/n Message += Environment.NewLine; byte[] bytesToSend = _useASCII ? Encoding.ASCII.GetBytes(Message) : Encoding.Unicode.GetBytes(Message); int bytesSent = _socket.Send(bytesToSend); } /// <summary> /// Clean up the socket. /// </summary> void IDisposable.Dispose() { try { _socket.Close(); RaiseOnDisconnect("Socket closed via Dispose method."); } catch { } try { _socket.Dispose(); } catch { } } /// <summary> /// This method will gracefully raise any delegated events if they exist. /// </summary> /// <param name="Message"></param> private void RaiseOnMessageReceived(string Message) { try //to raise delegates { OnMessageReceived(Message); } catch { } //when none exist ignore the Object Reference Error } /// <summary> /// This method will gracefully raise any delegated events if they exist. /// </summary> /// <param name="Message"></param> private void RaiseOnDisconnect(string Message) { try //to raise delegates { OnDisconnect(Message); } catch { } //when none exist ignore the Object Reference Error } } }
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。