這是一種伺服器跟客戶端呼叫的一種方法

前提要先準備好兩個憑證 一個有密碼的 附檔名會是pfx 沒密碼的會是cer 一個放在SERVER端 一個安裝在客戶端 已完成溝通
製作憑證的方法
Makecert -sv CertExpand1_TemporaryKey.pvk -n "CN=Yao" CertExpand1_TemporaryKey.cer -b 03/25/2013 -e 03/25/2020 -r

mekevert 是一個EXE 從VS的命令提示字元呼叫
客戶端

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Security;
using System.Net.Sockets;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

namespace SocketWeb
{
public partial class index : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{

}

protected void Button1_Click(object sender, EventArgs e)
{
SendToServer send = new SendToServer("127.0.0.1", 17170);
lblResult.Text = send.SendMsgToServer(txtMessage.Text.Trim());
}
}

public class SendToServer
{
public string HostAddress { get; set; }
public int HostPort { get; set; }

/// <summary>
/// 建構子,傳入伺服器IP及Port
/// </summary>
/// <param name="pHostAddress"></param>
/// <param name="pHostPort"></param>
public SendToServer(string pHostAddress, int pHostPort)
{
HostAddress = pHostAddress;
HostPort = pHostPort;
}

/// <summary>
/// 執行將訊息發送至伺服器方法
/// </summary>
/// <param name="pMessage"></param>
/// <returns></returns>
public string SendMsgToServer(string pMessage)
{
TcpClient client = new TcpClient(HostAddress, HostPort);
SslStream sslStream = new SslStream(client.GetStream(), false, new RemoteCertificateValidationCallback(ValidateServerCertificate), null);
X509CertificateCollection certs = new X509CertificateCollection();
X509Certificate cert = X509Certificate.CreateFromCertFile(HttpContext.Current.Server.MapPath(@"~/cer/SslSocket.cer"));
certs.Add(cert);
try
{
sslStream.AuthenticateAsClient("SslSocket", certs, System.Security.Authentication.SslProtocols.Tls, true);
}
catch (Exception ex)
{
client.Close();
return ex.Message;
}
byte[] messsage = Encoding.UTF8.GetBytes(string.Format("{0}<EOF>", pMessage));
sslStream.Write(messsage);
sslStream.Flush();
string serverMessage = ReadMessage(sslStream);
client.Close();
return serverMessage;
}

/// <summary>
/// 讀取訊息內容
/// </summary>
/// <param name="pSslStream"></param>
/// <returns></returns>
private string ReadMessage(SslStream pSslStream)
{
byte[] buffer = new byte[2048];
StringBuilder messageData = new StringBuilder();
int bytes = -1;
do
{
bytes = pSslStream.Read(buffer, 0, buffer.Length);

Decoder decoder = Encoding.UTF8.GetDecoder();
char[] chars = new char[decoder.GetCharCount(buffer, 0, bytes)];
decoder.GetChars(buffer, 0, bytes, chars, 0);
messageData.Append(chars);

if (messageData.ToString().IndexOf("<EOF>") != -1)
{
break;
}
} while (bytes != 0);

return messageData.ToString();
}

/// <summary>
/// 驗證服務器SSL憑證
/// </summary>
/// <param name="sender"></param>
/// <param name="certificate"></param>
/// <param name="chain"></param>
/// <param name="sslPolicyErrors"></param>
/// <returns></returns>
public static bool ValidateServerCertificate(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
{
if (sslPolicyErrors == SslPolicyErrors.None)
return true;
return false;
}
}
}

 

伺服器端

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Net.Security;
using System.Net.Sockets;
using System.Security.Authentication;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace SocketWIN
{
public partial class Form1 : Form
{
public static ListBox MainListBox;
public Form1()
{
InitializeComponent();
MainListBox = this.lbxMsg;
}

private void button1_Click(object sender, EventArgs e)
{
Thread socket = new Thread(RunSocket);
socket.IsBackground = true;
socket.Start();
}

private void button2_Click(object sender, EventArgs e)
{
SslSocket.StopServer();
}
private void RunSocket()
{
SslSocket.Certificate = Application.StartupPath + @"\SslSocket.pfx";
SslSocket.RunServer();
}
}

public sealed class SslSocket
{
private static TcpListener listener;
private static X509Certificate ServerCertificate = null;
private static bool IsRun = true;

private static string _Certificate = string.Empty;
public static string Certificate
{
get { return _Certificate; }
set { _Certificate = value; }
}

/// 執行伺服器監聽
public static void RunServer()
{

// 建立X509憑證
ServerCertificate = new X509Certificate(Certificate, "1");
// 監聽任何IP Address來的訊息
listener = new TcpListener(System.Net.IPAddress.Any, 17170);
// 開啟監聽
listener.Start();

while (IsRun)
{
UpdateStatus(string.Format("{0}-等待客戶端連接", DateTime.Now.ToString("HH:mm:ss")));
TcpClient client = listener.AcceptTcpClient();

if (!IsRun)
{
listener.Stop();
client.Close();
}
else
{
ProcessClient(client);
}
}
}

/// 停止伺服器監聽
public static void StopServer()
{
IsRun = false;
UpdateStatus(string.Format("{0}-停止客戶端連接", DateTime.Now.ToString("HH:mm:ss")));
}

/// 接收客戶端訊息處理並回覆
private static void ProcessClient(TcpClient pClient)
{
SslStream sslStream = new SslStream(pClient.GetStream(), true);

try
{
sslStream.AuthenticateAsServer(ServerCertificate, false, SslProtocols.Tls, true);
sslStream.ReadTimeout = 5000;
sslStream.WriteTimeout = 5000;
UpdateStatus(string.Format("{0}-等待客戶端訊息", DateTime.Now.ToString("HH:mm:ss")));

string messageData = ReadMessage(sslStream);

UpdateStatus(string.Format("{0}-接收訊息內容: {1}", DateTime.Now.ToString("HH:mm:ss"), messageData));
byte[] message = Encoding.UTF8.GetBytes(string.Format("伺服器接收此: {0} 訊息 " +
" 伺服器時間 " + DateTime.Now.ToString() +
" 字串長度 "+(messageData.Length - 5).ToString(), messageData));

UpdateStatus(string.Format("{0}-回覆客戶端訊息", DateTime.Now.ToString("HH:mm:ss")));
sslStream.Write(message);
}
catch (Exception)
{
sslStream.Close();
pClient.Close();
return;
}
finally
{
sslStream.Close();
pClient.Close();
}
}

/// 讀取訊息內容
private static string ReadMessage(SslStream pSslStream)
{
byte[] buffer = new byte[2048];
StringBuilder messageData = new StringBuilder();
int bytes = -1;
do
{
bytes = pSslStream.Read(buffer, 0, buffer.Length);

Decoder decoder = Encoding.UTF8.GetDecoder();
char[] chars = new char[decoder.GetCharCount(buffer, 0, bytes)];
decoder.GetChars(buffer, 0, bytes, chars, 0);
messageData.Append(chars);

if (messageData.ToString().IndexOf("<EOF>") != -1)
{
break;
}
} while (bytes != 0);
string a = messageData.ToString();
return a;
}

/// 更新主視窗ListBoxUI
private static void UpdateStatus(string pMessage)
{
Form1.MainListBox.Invoke(new Action(() => Form1.MainListBox.Items.Add(pMessage)));
}
}
}

arrow
arrow
    全站熱搜

    丁滿 發表在 痞客邦 留言(0) 人氣()