赞
踩
基于SSL协议的安全网络通信程序
****************************************
目录结构:
1. SSL理解
1.1 SSL的优点
1.2 SSL密文会话的安全机制
1.3 SSL工作过程
(1) SSL分层结构
(2) SSL握手过程
(3) 利用Wireshark分析SSL工作过程
2. X.509证书相关文件的生成
3. 实现SSL服务器和客户端
****************************************
1. SSL理解
1.1 SSL的优点
(1)提供较高的安全性保证。SSL利用数据加密、身份验证和消息完整性验证机制,保证数据传输的安全性。
(2)支持各种应用层协议。虽然SSL设计的初衷是为了解决Web安全性问题,但是由于SSL位于应用层和传输层之间,它可以为任何基于TCP等可靠连接的应用层协议提供安全性保证。
(3)部署简单。目前SSL己经成为网络中用来鉴别网站和网页浏览者身份,在客户端浏览器和Web服务器之间进行密文数据通信的全球化标准。SSL协议已被集成到大部分的浏览器中,如IE、Netscape、Firefox等。这就意味着几乎任意一台装有浏览器的计算机都支持SSL连接,不需要安装额外的客户端软件。
1.2 SSL密文会话的安全机制
(1)数据加密传输:数据需要加密后再进行传输,加密解密算法为对称密钥算法。
(2)身份验证:建立链接时需要对各通信对端进行身份验证,身份验证利用证书和数字签名技术,其中客户端的验证是可选的。
(3)消息完整性验证:消息传输过程中使用MAC算法来检验消息的完整性。
l 数据加密传输
与非对称密钥体制相比,对称密钥体制具有计算速度快的优点,通常用于对大量数据进行加密(如对整个数据流加密);而非对称密钥体制,一般用于数字签名和对少量的信息进行加密。SSL加密管道上的数据加解密使用对称密钥体制,目前主要支持的算法有DES、 3DES、 AES等,这些算法都可以有效地防止传输的数据被窃听。
l 身份验证
电子商务和网上银行等Web应用中必须保证客户要登录的Web服务器是真实的,以免重要信息被非法窃取。SSL安全协议利用数字签名来进行通信对端的身份验证。非对称密钥体制可以用来实现数字签名。由于通过私钥加密后的数据只能利用对应的公钥进行解密,因此根据解密是否成功,就可以判断发送者的身份,如同发送者对数据进行了 "签名"。
SSL客户端必须验证SSL服务器的身份,SSL服务器是否验证SSL客户端的身份,则由SSL服务器决定。使用数字签名验证身份时,需要确保被验证端的公钥是真实的,否则,非法用户可能会冒充被验证端与验证端通信。
l 消息完整性验证
为了避免网络中传输的数据被非法篡改,SSL利用基于MD5或SHA的MAC(消息认证码)算法来保证消息的完整性。
MAC算法要求通信双方具有相同的密钥,否则MAC值附件验证将会失败。因此,利用MAC算法验证消息完整性之前,需要在数据通信的双方部署相同的密钥。
l 利用非对称密钥算法保证密钥本身的安全
SSL利用非对称密钥体制加密密钥的方法來实现密钥交换,保证非授权的第三方无法获取相应的密钥。
利用非对称密钥算法加密对称密钥之前,Alice需要获取Bob的公钥,并保证该公钥确实属于Bob,否则,密钥可能会被未授权的非法用户窃取。SSL利用PKI提供的机制保证公钥的真实性。
l PKI保证公钥的真实性
数字证书(简称证书)是一个包含用户的公钥及其身份信息的文件,证明了客户与公钥的关联。数字证书由权威机构(CA)签发,并由CA保证数字证书的真实性。
验证SSL服务器/SSL客户端的身份之前,SSL服务器和SSL客户端需要将从CA获取的证书发送给通信对端,对端通过PKI判断该证书的真实性。如果该证书确实属于SSL服务器和SSL客户端,则通信对端利用该证书中的公钥验证SSL服务器和SSL客户端的身份。
1.3 SSL工作过程
(1) SSL分层结构
(2) SSL握手过程
SSL握手协议是SSL协议中最复杂的协议。SSL通过握手过程在客户端和服务器之间协商会话参数,并建立会话。会话包含的主要参数有会话ID、对方的证书、加密套件(密钥交换算法、数据加密算法和MAC算法等)以及主密钥(mastersecret)。通过SSL会话传输的数据,都将采用此次会话的主密钥和加密套件进行加密、计算MAC值等。
SSL握手协议由一系列报文组成,根据功能基本上可以分为四个阶段:
1) 第一阶段是建立安全能力。
2) 第二阶段是服务器鉴别和密钥交换。
3) 第三个阶段是客户鉴别和密钥交换。
4) 第四个阶段是完成握手阶段。
(3)利用Wireshark分析SSL工作过程
1.handshake--client hello
注释:
ECC算法和DH结合使用,用于密钥磋商,这个密钥交换算法称为ECDH。
使用RC4加密体制算法对通信数据加密(密钥长度128位)
使用SHA哈希算法进行消息完整性验证
使用RSA公钥体制算法进行证书验证和对称密钥交换
【既然密钥交换算法有很多种(RSA 和DH)那SSL握手期间用哪种呢,这个就是之前由选择的ciphersuit决定的,比如选择的是SSL_RSA_WITH_RC4_128_MD5 = 0x0004,那就是RSA的密钥交换算法即用非对称加密对称将密钥传送到对方,若选择的是SSL_DHE_RSA_EXPORT….那就使用DH交换算法】
2.handshake--server hello
3.S—>C handshake—certificate 服务器端向客户端发送服务器证书
【Certificate(可选):服务器发一个证书或一个证书链到客户端,证书链开始于服务器公共钥匙并结束于证明权威的根证书。该证书用于向客户端确认服务器的身份,该消息是可选的。如果配置服务器的SSL需要验证服务器的身份,会发送该消息。多数电子商务应用都需要服务器端身份验证。】
4.S-->Chandshake—sever key exchange handshake—sever hello done
服务器发送公钥和签名信息
【如果服务器发送的公共密钥对加密密钥的交换不是很合适,则发送一个服务器密钥交换消息。即和客户端协商密钥。】
RSA方式密钥交换消息则把消息中的加密用公钥放入会话缓存中,作为客户端这边握手阶段的写密钥而不是用服务器证书中的公钥。
DH 方式的消息就把消息中的 p,g,Ys三个参数(ECDH密钥交换情况下是G和A)记录下来,有这些 client端就可以计算出 pre-master了,只要回头再把自己这边的Yc参数发过去, server端就也能计算出相同的 pre-maseter了。
为了防止消息被恶意篡改,Server Key exchange消息中还要包含一个对密钥参数(pubKey)的签名(Signature)。
(1)serverkey exchange Pubkey signature
(2)Server hello done
5.C->S handshake—clientkey exchange
客户端产生一个会话密钥与服务器共享。在SSL握手协议完成后,客户端与服务器端通信信息的加密就会使用该会话密钥。如果使用RSA加密算法,客户端将使用服务器的公钥将会话密钥之后再发送给服务器。服务器使用自己的私钥对接收的消息进行解密得到共享的会话密钥。
若是 RSA 方式密钥交换,则产生一个 48 位随机数作为 pre-master 并用服务器公钥加密后发出去若是 DH 方式的密钥交换,则根据 sever 的 g,p,Ys ,产生 Xa 和 Yc , Xa 和 Ys 能计算出 pre-master ,把产生的 Yc 放入消息中发给server ,这样 server 用它的 Xb 和 Yc 也能计算出 pre-master 了。计算出预主密码后就顺便把主密码 (master secret) 给算出来了。算出主密码就把对称密钥产生出来了(预主要密码à主密码à对称密钥)
clientkey exchange, change cipher spec ,encrypted handshakemessage
【Change cipher spec:客户端要求服务器在后续的通信中使用加密模式】
6.S->C handshake—new session ticket
New session ticket,change cipher spec,encrypted handshake message
【Change cipher spec:服务器要求客户端在后续的通信中使用加密模式】
“session Ticket”(RFC 5077)取代机制被引入,目标是消除服务器需要维护每个客户端的会话状态缓存的要求。相反,如果客户指示它支持Session Ticket,在TLS握手的最后一步中服务器将包含一个“NewSession Ticket”信息,包含了一个加密通信所需要的信息,这些数据采用一个只有服务器知道的密钥进行加密。
】
以上1-6步,握手完成。下面开始客户端和服务器端开始传输加密信息。
7.C-->S 传送正式数据
【淘宝网登陆页面SSL连接建立分析】
42.156.196.14 https://login.taobao.com/member/login.jhtml
(1)C-->S client hello
(2)S-->C server hello
Ciphersuite:TLS_RSA_WITH_RC4_128_SHA
(3)S-->C certificate 证书链
(4)C-->S Client Key Exchange
RSA Encrypted Secret
(5)C-->S New Session Ticket
2. X.509证书相关文件的生成
【参考:基于X.509证书和SSL协议的身份认证过程实现http://h2appy.blog.51cto.com/609721/1181234】
生成数字证书相关文件的步骤:
1.生成服务器端的私钥(key文件),执行命令
openssl genrsa -des3 -out server.key1024
Enter pass phrase for server.key:123456
2.生成服务器端的csr文件
openssl req -new -key server.key -outserver.csr -config openssl.cnf
===拷贝 openssl\apps 下的openssl.cnf文档到out32dll目录下,就可以使用 Openssl了。
Enter pass phrase for server.key:123456
A challenge password:147258
3.客户端生成key文件
openssl genrsa -des3 -out client.key1024
Enter pass phrase for client.key:123456
4.生成客户端的csr文件
openssl req -new -key client.key -outclient.csr -config openssl.cnf
Enter pass phrase for client.key:123456
A challenge password:147258
5.生成自己的CA
openssl req -new -x509 -keyout ca.key -outca.crt -config openssl.cnf
Enter PEM pass phrase:123456
生成ca.key和ca.crt证书文件
6.用生成的ca给服务器的csr文件签名,生成服务器端的证书
openssl ca -in server.csr -out server.crt-cert ca.crt -keyfile ca.key -config openssl.cnf
===将apps目录下的demoCA目录以及根目录下的crypto目录复制到out32dll目录下;并在demoCA目录下新建文件夹newcerts.
Enter pass phrase for ca.key:123456
7.用生成的ca给客户端的csr文件签名,生成客户端的证书
openssl ca -in client.csr -out client.crt-cert ca.crt -keyfile ca.key -config openssl.cnf
===清空index.txt文件内容后正常生成
Enter pass phrase for ca.key:123456
生成的相关文件如下图所示:
3. 实现SSL服务器和客户端
对于上面的证书生成过程中,SSL服务器和客户端中所需要使用的只有五个文件,分别是ca.crt,client.crt,client.key,server.crt和server.key。
客户端需要ca.crt,client.crt,client.key这三个文件,
服务器端需要ca.crt,server.crt,server.key这三个文件。
源代码:
SSL Server端:
- //
- #include "openssl/rsa.h"
- #include "openssl/crypto.h"
- #include "openssl/x509.h"
- #include "openssl/pem.h"
- #include "openssl/ssl.h"
- #include "openssl/err.h"
- #include "openssl/rand.h"
- #include <iostream>
-
- using namespace std;
-
- #pragma comment(lib, "libeay32.lib")
- #pragma comment(lib, "ssleay32.lib")
-
- /*所有需要的参数信息都在此处以#define的形式提供*/
-
- #define CERTF "D:\\openssl-1.0.1e\\out32dll\\server.crt" /*客户端的证书(需经CA签名)*/
- #define KEYF "D:\\openssl-1.0.1e\\out32dll\\server.key" /*客户端的私钥(建议加密存储)*/
- #define CACERT "D:\\openssl-1.0.1e\\out32dll\\ca.crt" /*CA 的证书*/
- #define PORT 7758 /*服务端的端口*/
-
- #define CHK_NULL(x) if ((x)==NULL) { printf("null\n"); }
- #define MAXLEN 4096
-
- int main ()
- {
- int err;
-
- int ListenSock;//监听套接字
- int ConnectSock;//连接套接字
-
- SSL_CTX* ctx;
- SSL* ssl;
- X509* client_cert;
- // char* str;
- char buf [MAXLEN] = {0};
- // char szMsg[4096] = {0};
- //SSL_METHOD *meth;
-
- WSADATA wsaData;
- system("title SSL_SERVER");
- system("color 0a");
- if(WSAStartup(MAKEWORD(2,2),&wsaData) != 0){
- printf("WSAStartup()fail:%d\n",GetLastError());
- return -1;
- }
-
-
- OpenSSL_add_ssl_algorithms(); /*初始化*/
- SSL_load_error_strings(); /*为打印调试信息作准备*/
-
- //注意这里是server和和客户端不同
- //meth=TLSv1_server_method();
- ctx = SSL_CTX_new (TLSv1_server_method()); //采用什么协议(SSLv2/SSLv3/TLSv1)在此指定
- CHK_NULL(ctx);
-
- SSL_CTX_set_verify(ctx,SSL_VERIFY_PEER,NULL); /*验证与否*/
- SSL_CTX_load_verify_locations(ctx,CACERT,NULL); /*若验证,则放置CA证书*/
-
-
- if (SSL_CTX_use_certificate_file(ctx, CERTF, SSL_FILETYPE_PEM) <= 0)
- {
- cout<<"服务器端证书检查失败!"<<endl;
- exit(0);
- }
-
- if (SSL_CTX_use_PrivateKey_file(ctx, KEYF, SSL_FILETYPE_PEM) <= 0)
- {
- cout <<"服务器端key检查失败!"<<endl;
- system("pause");
- exit(0);
- }
- else
- {
- cout<<"服务器端key检查成功!"<<endl;
- }
-
- if (!SSL_CTX_check_private_key(ctx))
- {
- cout << "服务器端证书和key不匹配!"<<endl;
- exit(0);
- }
- SSL_CTX_set_cipher_list(ctx,"AES128-SHA");//*********加密方式 1.4******
- SSL_CTX_set_mode(ctx, SSL_MODE_AUTO_RETRY); //不需要任何重试请求
-
-
- //创建监听套接字
- ListenSock = socket (AF_INET, SOCK_STREAM, 0);
- if(ListenSock == INVALID_SOCKET)
- {
- cout << "监听套接字创建失败" << endl;
- exit(0);
- }
-
- //创建地址
- sockaddr_in sin = {0};
- sin.sin_family = AF_INET;
- sin.sin_addr.s_addr = INADDR_ANY;
- sin.sin_port = htons (PORT); //Servert Port Number
-
- //套接字绑定
- err = bind(ListenSock, (struct sockaddr*)&sin,sizeof(sin));
- if(err == -1)
- {
- cout << "监听套接字绑定失败" << endl;
- exit(0);
- }
-
- /*接受TCP链接*/
- err = listen (ListenSock, 5); //等待连接的队列的最大长度为5
- if(err == -1)
- {
- cout << "监听套接字开启监听失败" << endl;
- exit(0);
- }
-
- //接受客户端连接
- struct sockaddr_in sa_client;
- int len=sizeof(struct sockaddr);
- ConnectSock = accept(ListenSock, (struct sockaddr *)&sa_client, &len);
- if(err == -1)
- {
- cout << "监听套接字accept失败" << endl;
- exit(0);
- }
-
- cout<<"Connection from "<<inet_ntoa(sa_client.sin_addr)<<",port:"<<ntohs(sa_client.sin_port)<<"............"<<endl;
- closesocket (ListenSock); //**********
-
-
- /*--------------------TCP连接已建立,进行服务端的SSL过程.--------------- */
- cout << "TCP连接建立,创建SSL连接中....\n" << endl;
- //从初始化的ctx新建SSL
- ssl = SSL_new (ctx);
- if(ssl == NULL)
- {
- cout << "SSL创建失败" << endl;
- exit(0);
- }
-
- //(连接)套接字和SSL绑定 //<------------key
- SSL_set_fd (ssl, ConnectSock);
- // SSL连接建立
- err = SSL_accept (ssl);//等待一个TLS / SSL客户端启动TLS / SSL握手,类似于socket中的accept。
- if(err == -1)
- {
- cout << "创建SSL连接失败" << endl;
- exit(0);
- }
- else
- {
- cout << "创建SSL连接成功" << endl;
- }
-
- /*打印所有加密算法的信息(可选)*/
- cout << "SSL连接算法信息:" << SSL_get_cipher (ssl) << endl;
- /*得到客户端的证书并打印些信息(可选) */
- client_cert = SSL_get_peer_certificate (ssl);
- if (client_cert != NULL) {
- cout << "客户端证书:" << endl;
- cout << "subject:" <<X509_NAME_oneline(X509_get_subject_name (client_cert), 0, 0)<< endl;
- cout << "issuer:" <<X509_NAME_oneline(X509_get_issuer_name (client_cert),0,0) << endl;
- // CHK_NULL(str);
- X509_free (client_cert);/*如不再需要,需将证书释放 */
- }
- else cout << "客户端没有证书信息!" << endl; //客户端认证失败
-
-
- //SSL通信,用SSL_write,SSL_read代替send和recv
- while(true)
- {
- //接收消息
- err = SSL_read (ssl, buf, sizeof(buf) - 1);
- if(err == -1)
- {
- cout << "SSL_read接收消息失败" << endl;
- exit(0);
- }
- buf[err] = '\0';
- cout << "【Client】:" << buf << endl;
-
- //发送消息
- cout << "请输入要发送的消息:";
- gets(buf);//end with CRLF or EOF
- err = SSL_write(ssl, buf, strlen(buf));
- if(err == -1)
- {
- cout << "SSL_write发送消息失败" << endl;
- exit(0);
- }
- cout << "【Server】:" << buf << endl;
- }
-
- //关闭套接字和ssl
- SSL_shutdown (ssl);
- shutdown (ConnectSock,2);
- SSL_free (ssl);
- SSL_CTX_free (ctx);
- closesocket(ConnectSock);
- return 0;
- }
SSL Client 端:
- //
- #include "openssl/rsa.h"
- #include "openssl/crypto.h"
- #include "openssl/x509.h"
- #include "openssl/pem.h"
- #include "openssl/ssl.h"
- #include "openssl/err.h"
- #include "openssl/rand.h"
- #include <iostream>
- using namespace std;
-
- #pragma comment(lib, "libeay32.lib")
- #pragma comment(lib, "ssleay32.lib")
-
- /*所有需要的参数信息都在此处以#define的形式提供*/
-
- #define CERTF "D:\\openssl-1.0.1e\\out32dll\\client.crt" /*客户端的证书(需经CA签名)*/
- #define KEYF "D:\\openssl-1.0.1e\\out32dll\\client.key" /*客户端的私钥(建议加密存储)*/
- #define CACERT "D:\\openssl-1.0.1e\\out32dll\\ca.crt" /*CA 的证书*/
- #define PORT 7758 /*服务端的端口*/
- #define CHK_NULL(x) if ((x)==NULL) { printf("null\n"); }
- #define MAXLEN 4096
-
- int main ()
- {
- int err;
- int sd;
-
- struct sockaddr_in sa;
- SSL_CTX* ctx;
- SSL* ssl;
- X509* server_cert;
- // char* str;
- char buf [MAXLEN] = {0};
- // char szMsg[MAXLEN] = {0};
- //SSL_METHOD *meth;
- //int seed_int[100]; /*存放随机序列*/
-
- WSADATA wsaData;
-
- if(WSAStartup(MAKEWORD(2,2),&wsaData) != 0){
- printf("WSAStartup()fail:%d\n",GetLastError());
- return -1;
- }
- system("title SSL_CLIENT");
- system("color 0a");
- OpenSSL_add_ssl_algorithms(); /*1.SSL初始化*/
- SSL_load_error_strings(); /*2.SSL错误信息初始化 为打印调试信息作准备*/
-
- //注意这里是client和和服务器不同
- ctx = SSL_CTX_new (TLSv1_client_method()); //3.创建本次会话所使用的协议(TLSv1); 4.申请SSL会话的环境
- CHK_NULL(ctx);
- //SSL_VERIFY_PEER:希望验证对方的证书
- SSL_CTX_set_verify(ctx,SSL_VERIFY_PEER,NULL); /*验证与否*/ //5.设置会话的握手方式
- SSL_CTX_load_verify_locations(ctx,CACERT,NULL); /*若验证,则放置CA证书*/ //6.并加载CA证书
-
-
- if (SSL_CTX_use_certificate_file(ctx, CERTF, SSL_FILETYPE_PEM) <= 0) //7.加载自己(客户端)的整数
- {
- cout << "客户端证书检查失败!" << endl;
- exit(0);
- }
- if (SSL_CTX_use_PrivateKey_file(ctx, KEYF, SSL_FILETYPE_PEM) <= 0) //8.加载客户端的私钥
- {
- cout << "客户端key检查失败!" << endl;
- system("pause");
- exit(0);
- }
- else
- {
- cout<<"客户端证key检查成功!"<<endl;
- }
-
- if (!SSL_CTX_check_private_key(ctx))//9.检查自己的证书和私钥是否匹配
- {
- cout << "客户端证书和key不匹配!" << endl;
- exit(0);
- }
-
- //10.加密方式
- // SSL_CTX_set_cipher_list(ctx, "RC4-MD5");
- SSL_CTX_set_cipher_list(ctx, "AES128-SHA");
-
- //处理握手多次
- //设置ssl的模式为SSL_MODE_AUTO_RETRY,使用这个选项进行设置,如果服务器突然希望进行一次新的握手,那么OpenSSL可以在后台处理它。
- SSL_CTX_set_mode(ctx, SSL_MODE_AUTO_RETRY);
-
- /*构建随机数生成机制,WIN32平台必需*/
- /* srand( (unsigned)time( NULL ) );
- for( int i = 0; i < 100;i++ ) seed_int[i] = rand();
- RAND_seed(seed_int, sizeof(seed_int));*/
-
- //11.创建TCP连接请求
- sd = socket (AF_INET, SOCK_STREAM, 0);
- if(sd == INVALID_SOCKET)
- {
- cout << "套接字创建失败!" << endl;
- exit(0);
- }
- memset(&sa,'\0', sizeof(sa));
- sa.sin_family = AF_INET;
-
- // 获取本地地址信息
- // unsigned int SrcIp;
- /* char szLocalName[MAXLEN]={0};
- gethostname(szLocalName,MAXLEN);
- hostent* pHost=gethostbyname(szLocalName);
- if(pHost!=NULL)
- memcpy(&(sa.sin_addr.s_addr),pHost->h_addr_list[0],pHost->h_length);
- else
- exit(0);*/
-
- sa.sin_addr.s_addr = inet_addr ("127.0.0.1");
- // sa.sin_addr.s_addr = inet_addr ("192.168.146.1");
-
- sa.sin_port = htons (PORT); /* Server Port number *///SERVER PORT
-
- //TCP连接 等待服务器的响应
- cout<<"等待连接中..."<<endl;
- int try_count=0;
- while(1)
- {
- err = connect(sd, (struct sockaddr*) &sa,sizeof(sa));
- if(try_count>5)
- {
- cout<<"TCP 连接超时..."<<endl;
- system("pause");
- exit(1);
- }
-
- else
- {
- if(err == -1)
- {
- // cout << "TCP连接失败!" << endl;
- try_count++;
- continue;
- }
- else
- {
- cout << "TCP连接成功!" << endl;
- break;
- }
- }
- }
-
- /* 12.TCP 链接已建立.开始 SSL 握手过程.......................... */
- //SSL连接
- //新建SSL
- ssl = SSL_new (ctx); //利用SSL会话的环境ctx申请SSL
- if(ssl == NULL)
- {
- cout << "新建SSL失败!" << endl;
- exit(0);
- }
- //13. 套接字sd和SSL绑定
- SSL_set_fd (ssl, sd);
- //14.SLL连接(SSL handshake)
- //设置等待服务器响应的超时时间
- while(1)
- {
- err = SSL_connect (ssl);
- if(err == -1)
- {
- cout << "SSL连接失败" << endl;
- continue;
- }
-
- else
- {
- cout << "SSL连接成功" << endl;
- break;
- }
- }
-
- //打印连接信息
- cout << "SSL连接算法信息:" << SSL_get_cipher (ssl) << endl;
- /*得到服务端的证书并打印些信息(可选) */
- server_cert = SSL_get_peer_certificate (ssl);//从SSL套接字中提取对方的证书信息,这些信息已经被SSL验证过了
- if (server_cert != NULL) {
- cout << "服务器证书:" << endl;
- cout << "subject:" << X509_NAME_oneline( X509_get_subject_name (server_cert), 0, 0)<< endl;//得到证书所用者的名字
- cout << "issuer:" << X509_NAME_oneline (X509_get_issuer_name (server_cert),0,0) << endl;
- // CHK_NULL(str);
- X509_free (server_cert);/*如不再需要,需将证书释放 */
- }
- else cout << "服务器没有证书信息!" << endl; //服务器端认证失败
-
- //SSL通信,用SSL_write,SSL_read代替send和recv
- while(true)
- {
- //发送消息 int SSL_write(SSL *ssl,const void *buf,int num);
- cout << "请输入要发送的消息:";
- gets(buf);
- err = SSL_write(ssl, buf, strlen(buf));
- if(err == -1)
- {
- cout << "SSL_write发送消息失败" << endl;
- exit(0);
- }
- cout << "【Client】:" << buf << endl;
-
- //接收消息 int SSL_read(SSL *ssl,void *buf,int num);
- err = SSL_read (ssl, buf, sizeof(buf) - 1);
- if(err == -1)
- {
- cout << "SSL_read接收消息失败" << endl;
- exit(0);
- }
- buf[err] = '\0';
- cout << "【Server】:" << buf << endl;
- }
-
- /* 收尾工作 */
- SSL_shutdown (ssl);//关闭SSL套接字
- //shutdown( SOCKET s, int how); 0关闭套接字的读功能 1关闭套接字的写功能 2关闭套接字的读写功能
- //请注意shutdown()函数并不关闭套接口,且套接口所占有的资源将被一直保持到closesocket()调用。
- //shutdown (sd,2);//
- SSL_free (ssl);//释放SSL套接字
- SSL_CTX_free (ctx);//释放SSL会话环境
- closesocket(sd);//
- return 0;
- }
运行结果示例:
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。