gpt4 book ai didi

c# 与 c++ ssl_connect

转载 作者:塔克拉玛干 更新时间:2023-11-03 02:17:59 27 4
gpt4 key购买 nike

你好,我有一个使用 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 库,我从 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", 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
}

}
}

关于c# 与 c++ ssl_connect,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20009376/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com