c# vs c++ ssl_connect
c# vs c++ ssl_connect
你好,我有一个使用 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, 0, &dwSize, NULL, 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);
我在这个 c++ 应用程序中使用静态 ssl 库,我从这里下载了它
一切正常,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", CallingConvention = CallingConvention.Cdecl, EntryPoint = "SSL_write")]
public static extern int SSL_Write(IntPtr ssl, byte[] buf, int num);
[DllImport("ssleay32.dll", CallingConvention = CallingConvention.Cdecl, 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", CallingConvention = CallingConvention.Cdecl, EntryPoint = "SSL_new")]
extern public static IntPtr SSL_new(IntPtr ctx);
[DllImport("ssleay32.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "SSL_connect")]
extern public static int SSL_connect(IntPtr ssl);
[DllImport("ssleay32.dll",CallingConvention= CallingConvention.Cdecl, EntryPoint = "SSL_load_error_strings")]
extern public static void SSL_load_error_strings();
[DllImport("ssleay32.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "SSL_library_init")]
extern public static int SSL_library_init();
[DllImport("ssleay32.dll",CallingConvention= CallingConvention.Cdecl, EntryPoint = "SSLeay_add_all_algorithms")]
extern public static int SSLeay_add_all_algorithms();
[DllImport("ssleay32.dll",CallingConvention= CallingConvention.Cdecl, EntryPoint = "SSLv23_client_method")]
extern public static IntPtr SSLv23_client_method();
[DllImport("ssleay32.dll",CallingConvention= CallingConvention.Cdecl, EntryPoint = "SSLv3_client_method")]
extern public static IntPtr SSLv3_client_method();
[DllImport("ssleay32.dll",CallingConvention= CallingConvention.Cdecl, EntryPoint = "SSL_CTX_free")]
extern public static void SSL_CTX_free(IntPtr ctx);
[DllImport("ssleay32.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "SSL_free")]
extern public static void SSL_free(IntPtr ssl);
[DllImport("ssleay32.dll",CallingConvention= CallingConvention.Cdecl, EntryPoint = "SSL_get_error")]
extern public static int SSL_get_error(IntPtr ssl, int ret);
[DllImport("ssleay32.dll",CallingConvention= CallingConvention.Cdecl, EntryPoint = " SSL_CTX_set_mode")]
extern public static long SSL_CTX_set_mode(IntPtr ctx, long mode);
[DllImport("libeay32", CallingConvention = CallingConvention.Cdecl, EntryPoint = "OPENSSL_add_all_algorithms_noconf")]
extern public static void OpenSSL_add_all_algorithms();
[DllImport("libeay32", CallingConvention = CallingConvention.Cdecl, EntryPoint = "ERR_get_error")]
extern public static int ERR_get_error();
[DllImport("ssleay32.dll", CallingConvention = CallingConvention.Cdecl, EntryPoint = "SSL_CTX_ctrl")]
public extern static int SSL_CTX_ctrl(IntPtr ctx, int cmd, int arg, IntPtr parg);
[DllImport("ssleay32.dll", CallingConvention = CallingConvention.Cdecl, 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 = 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套接字与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, SocketType.Stream, 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, 0, bytesReceived) :
Encoding.Unicode.GetString(stateObject.buffer, 0, 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
}
}
}
- SSL上的`curl_easy_send`和`curl_asy_recv`:如何处理`CURLE_AGAIN`
- WinSock2:connect() 提供"连接被拒绝"
- 使用 OpenSSL 从内存中读取原始 SSL/TLS 证书
- 如何使用connect将qml按钮与同一类的cpp函数连接起来
- Mongocxx无法使用SSL连接到mongoDB
- 在 QTextEdit 中使用指针或在 Qt-Creator 上使用 connect()
- gnuradio c++ connect self() throw bad_weak_ptr
- 如何使用MinGW编译器和SSL支持静态编译Qt
- curl_easy_perform() 失败:SSL 对等证书或 SSH 远程密钥不正常
- 如何在 Windows 中通过 SSL 端口枚举域控制器
- 如何将函数指针传递给方法,以便它可以在Qt的connect()中使用?
- 我需要帮助来缩短检索 SSL 证书的执行时间
- Windows 和 Android 应用程序是否需要 SSL?
- 在CTOR vs Connect方法中提升套接字与stream_socket端点
- Make zmqpp::socket::connect a std::future
- 如何使用QWebEngineView忽略SSL证书错误
- CPPRestSdk给出错误SSL错误:WINHTTP_CALLBACK_STATUS_FLAG_INVALID_CA
- 成功完成TLS握手后,服务器关闭时出现错误的SSL例程:SSL3_GET_RECORD:错误的版本号
- C-Free and MySQL connect
- 当我使用Connect信号和插槽时,会出现此分解错误