服务端程序流程

 #include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/wait.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <openssl/ssl.h>
#include <openssl/err.h> #define MAXBUF 1024
/************关于本文档********************************************
*filename: ssl-server.c
*purpose: 演示利用 OpenSSL 库进行基于 IP层的 SSL 加密通讯的方法,这是服务器端例子
*wrote by: zhoulifa(zhoulifa@163.com) 周立发(http://zhoulifa.bokee.com)
Linux爱好者 Linux知识传播者 SOHO族 开发者 最擅长C语言
*date time:2007-02-02 19:40
*Note: 任何人可以任意复制代码并运用这些文档,当然包括你的商业用途
* 但请遵循GPL
*Thanks to:Google
*Hope:希望越来越多的人贡献自己的力量,为科学技术发展出力
* 科技站在巨人的肩膀上进步更快!感谢有开源前辈的贡献!
*********************************************************************/
int main(int argc, char **argv)
{
int sockfd, new_fd;
socklen_t len;
struct sockaddr_in my_addr, their_addr;
unsigned int myport, lisnum;
char buf[MAXBUF + ];
SSL_CTX *ctx; if (argv[])
myport = atoi(argv[]);
else
myport = ; if (argv[])
lisnum = atoi(argv[]);
else
lisnum = ; /* SSL 库初始化 */
SSL_library_init();
/* 载入所有 SSL 算法 */
OpenSSL_add_all_algorithms();
/* 载入所有 SSL 错误消息 */
SSL_load_error_strings();
/* 以 SSL V2 和 V3 标准兼容方式产生一个 SSL_CTX ,即 SSL Content Text */
ctx = SSL_CTX_new(SSLv23_server_method());
/* 也可以用 SSLv2_server_method() 或 SSLv3_server_method() 单独表示 V2 或 V3标准 */
if (ctx == NULL) {
ERR_print_errors_fp(stdout);
exit();
}
/* 载入用户的数字证书, 此证书用来发送给客户端。 证书里包含有公钥 */
if (SSL_CTX_use_certificate_file(ctx, argv[], SSL_FILETYPE_PEM) <= ) {
ERR_print_errors_fp(stdout);
exit();
}
/* 载入用户私钥 */
if (SSL_CTX_use_PrivateKey_file(ctx, argv[], SSL_FILETYPE_PEM) <= ) {
ERR_print_errors_fp(stdout);
exit();
}
/* 检查用户私钥是否正确 */
if (!SSL_CTX_check_private_key(ctx)) {
ERR_print_errors_fp(stdout);
exit();
} /* 开启一个 socket 监听 */
if ((sockfd = socket(PF_INET, SOCK_STREAM, )) == -) {
perror("socket");
exit();
} else
printf("socket created\n"); bzero(&my_addr, sizeof(my_addr));
my_addr.sin_family = PF_INET;
my_addr.sin_port = htons(myport);
if (argv[])
my_addr.sin_addr.s_addr = inet_addr(argv[]);
else
my_addr.sin_addr.s_addr = INADDR_ANY; if (bind(sockfd, (struct sockaddr *) &my_addr, sizeof(struct sockaddr))
== -) {
perror("bind");
exit();
} else
printf("binded\n"); if (listen(sockfd, lisnum) == -) {
perror("listen");
exit();
} else
printf("begin listen\n"); while () {
SSL *ssl;
len = sizeof(struct sockaddr);
/* 等待客户端连上来 */
if ((new_fd =
accept(sockfd, (struct sockaddr *) &their_addr,
&len)) == -) {
perror("accept");
exit(errno);
} else
printf("server: got connection from %s, port %d, socket %d\n",
inet_ntoa(their_addr.sin_addr),
ntohs(their_addr.sin_port), new_fd); /* 基于 ctx 产生一个新的 SSL */
ssl = SSL_new(ctx);
/* 将连接用户的 socket 加入到 SSL */
SSL_set_fd(ssl, new_fd);
/* 建立 SSL 连接 */
if (SSL_accept(ssl) == -) {
perror("accept");
close(new_fd);
break;
} /* 开始处理每个新连接上的数据收发 */
bzero(buf, MAXBUF + );
strcpy(buf, "server->client");
/* 发消息给客户端 */
len = SSL_write(ssl, buf, strlen(buf)); if (len <= ) {
printf
("消息'%s'发送失败!错误代码是%d,错误信息是'%s'\n",
buf, errno, strerror(errno));
goto finish;
} else
printf("消息'%s'发送成功,共发送了%d个字节!\n",
buf, len); bzero(buf, MAXBUF + );
/* 接收客户端的消息 */
len = SSL_read(ssl, buf, MAXBUF);
if (len > )
printf("接收消息成功:'%s',共%d个字节的数据\n",
buf, len);
else
printf
("消息接收失败!错误代码是%d,错误信息是'%s'\n",
errno, strerror(errno));
/* 处理每个新连接上的数据收发结束 */
finish:
/* 关闭 SSL 连接 */
SSL_shutdown(ssl);
/* 释放 SSL */
SSL_free(ssl);
/* 关闭 socket */
close(new_fd);
} /* 关闭监听的 socket */
close(sockfd);
/* 释放 CTX */
SSL_CTX_free(ctx);
return ;
}

客户端编写流程

 #include <string.h>
#include <errno.h>
#include <sys/socket.h>
#include <resolv.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <openssl/ssl.h>
#include <openssl/err.h> #define MAXBUF 1024 void ShowCerts(SSL * ssl)
{
X509 *cert;
char *line; cert = SSL_get_peer_certificate(ssl);
if (cert != NULL) {
printf("数字证书信息:\n");
line = X509_NAME_oneline(X509_get_subject_name(cert), , );
printf("证书: %s\n", line);
free(line);
line = X509_NAME_oneline(X509_get_issuer_name(cert), , );
printf("颁发者: %s\n", line);
free(line);
X509_free(cert);
} else
printf("无证书信息!\n");
}
/************关于本文档********************************************
*filename: ssl-client.c
*purpose: 演示利用 OpenSSL 库进行基于 IP层的 SSL 加密通讯的方法,这是客户端例子
*wrote by: zhoulifa(zhoulifa@163.com) 周立发(http://zhoulifa.bokee.com)
Linux爱好者 Linux知识传播者 SOHO族 开发者 最擅长C语言
*date time:2007-02-02 20:10
*Note: 任何人可以任意复制代码并运用这些文档,当然包括你的商业用途
* 但请遵循GPL
*Thanks to:Google
*Hope:希望越来越多的人贡献自己的力量,为科学技术发展出力
* 科技站在巨人的肩膀上进步更快!感谢有开源前辈的贡献!
*********************************************************************/
int main(int argc, char **argv)
{
int sockfd, len;
struct sockaddr_in dest;
char buffer[MAXBUF + ];
SSL_CTX *ctx;
SSL *ssl; if (argc != ) {
printf
("参数格式错误!正确用法如下:\n\t\t%s IP地址 端口\n\t比如:\t%s 127.0.0.1 80
\n此程序用来从某个 IP 地址的服务器某个端口接收最多 MAXBUF 个字节的消息",
argv[], argv[]);
exit();
} /* SSL 库初始化,参看 ssl-server.c 代码 */
SSL_library_init();
OpenSSL_add_all_algorithms();
SSL_load_error_strings();
ctx = SSL_CTX_new(SSLv23_client_method());
if (ctx == NULL) {
ERR_print_errors_fp(stdout);
exit();
} /* 创建一个 socket 用于 tcp 通信 */
if ((sockfd = socket(AF_INET, SOCK_STREAM, )) < ) {
perror("Socket");
exit(errno);
}
printf("socket created\n"); /* 初始化服务器端(对方)的地址和端口信息 */
bzero(&dest, sizeof(dest));
dest.sin_family = AF_INET;
dest.sin_port = htons(atoi(argv[]));
if (inet_aton(argv[], (struct in_addr *) &dest.sin_addr.s_addr) == ) {
perror(argv[]);
exit(errno);
}
printf("address created\n"); /* 连接服务器 */
if (connect(sockfd, (struct sockaddr *) &dest, sizeof(dest)) != ) {
perror("Connect ");
exit(errno);
}
printf("server connected\n"); /* 基于 ctx 产生一个新的 SSL */
ssl = SSL_new(ctx);
SSL_set_fd(ssl, sockfd);
/* 建立 SSL 连接 */
if (SSL_connect(ssl) == -)
ERR_print_errors_fp(stderr);
else {
printf("Connected with %s encryption\n", SSL_get_cipher(ssl));
ShowCerts(ssl);
} /* 接收对方发过来的消息,最多接收 MAXBUF 个字节 */
bzero(buffer, MAXBUF + );
/* 接收服务器来的消息 */
len = SSL_read(ssl, buffer, MAXBUF);
if (len > )
printf("接收消息成功:'%s',共%d个字节的数据\n",
buffer, len);
else {
printf
("消息接收失败!错误代码是%d,错误信息是'%s'\n",
errno, strerror(errno));
goto finish;
}
bzero(buffer, MAXBUF + );
strcpy(buffer, "from client->server");
/* 发消息给服务器 */
len = SSL_write(ssl, buffer, strlen(buffer));
if (len < )
printf
("消息'%s'发送失败!错误代码是%d,错误信息是'%s'\n",
buffer, errno, strerror(errno));
else
printf("消息'%s'发送成功,共发送了%d个字节!\n",
buffer, len); finish:
/* 关闭连接 */
SSL_shutdown(ssl);
SSL_free(ssl);
close(sockfd);
SSL_CTX_free(ctx);
return ;
}

编译程序用如下命令:

gcc -Wall ssl-client.c -o client -lssl -lcrypto
gcc -Wall ssl-server.c -o server -lssl -lcrypto

证书 privkey.pem 和 cacert.pem 生成使用如下命令(具体请参考 “OpenSSL体系下使用密钥数字证书等”):

openssl genrsa -out privkey.pem
openssl req -new -x509 -key privkey.pem -out cacert.pem -days

运行程序使用如下命令:

./server   127.0.0.1 cacert.pem privkey.pem
./client 127.0.0.1

运行截图如下:

服务端:

客户端:

参考资料:

1、http://blog.csdn.net/thq0201/article/details/6766449#

2、http://blog.chinaunix.net/uid-20682147-id-76392.html

3、http://zhoulifa.bokee.com

ssl客户端与服务端通信的demo的更多相关文章

  1. Android BLE与终端通信(三)——客户端与服务端通信过程以及实现数据通信

    Android BLE与终端通信(三)--客户端与服务端通信过程以及实现数据通信 前面的终究只是小知识点,上不了台面,也只能算是起到一个科普的作用,而同步到实际的开发上去,今天就来延续前两篇实现蓝牙主 ...

  2. netty-3.客户端与服务端通信

    (原) 第三篇,客户端与服务端通信 以下例子逻辑: 如果客户端连上服务端,服务端控制台就显示,XXX个客户端地址连接上线. 第一个客户端连接成功后,客户端控制台不显示信息,再有其它客户端再连接上线,则 ...

  3. Netty入门之客户端与服务端通信(二)

    Netty入门之客户端与服务端通信(二) 一.简介 在上一篇博文中笔者写了关于Netty入门级的Hello World程序.书接上回,本博文是关于客户端与服务端的通信,感觉也没什么好说的了,直接上代码 ...

  4. 基于开源SuperSocket实现客户端和服务端通信项目实战

    一.课程介绍 本期带给大家分享的是基于SuperSocket的项目实战,阿笨在实际工作中遇到的真实业务场景,请跟随阿笨的视角去如何实现打通B/S与C/S网络通讯,如果您对本期的<基于开源Supe ...

  5. Python进阶----SOCKET套接字基础, 客户端与服务端通信, 执行远端命令.

    Python进阶----SOCKET套接字基础, 客户端与服务端通信, 执行远端命令. 一丶socket套接字 什么是socket套接字: ​ ​  ​ 专业理解: socket是应用层与TCP/IP ...

  6. Netty入门——客户端与服务端通信

    Netty简介Netty是一个基于JAVA NIO 类库的异步通信框架,它的架构特点是:异步非阻塞.基于事件驱动.高性能.高可靠性和高可定制性.换句话说,Netty是一个NIO框架,使用它可以简单快速 ...

  7. Python socket编程客户端与服务端通信

    [本文出自天外归云的博客园] 目标:实现客户端与服务端的socket通信,消息传输. 客户端 客户端代码: from socket import socket,AF_INET,SOCK_STREAM ...

  8. 实验09——java基于TCP实现客户端与服务端通信

    TCP通信         需要先创建连接 - 并且在创建连接的过程中 需要经过三次握手        底层通过 流 发送数据 数据没有大小限制        可靠的传输机制 - 丢包重发 包的顺序的 ...

  9. 二、网络编程-socket之TCP协议开发客户端和服务端通信

    知识点:之前讲的udp协议传输数据是不安全的,不可靠不稳定的,tcp协议传输数据安全可靠,因为它们的通讯机制是不一样的.udp是用户数据报传输,也就是直接丢一个数据包给另外一个程序,就好比寄信给别人, ...

随机推荐

  1. 【.NET深呼吸】基于异步上下文的本地变量(AsyncLocal)

    在开始吹牛之前,老周说两个故事. 第一个故事是关于最近某些别有用心的人攻击.net的事,其实我们不用管它们,只要咱们知道自己是.net爱好者就行了,咱们就是因为热爱.net才会选择它.这些人在这段时间 ...

  2. Windows 批处理

    1. 引言     在Windows上,经常需要做一些重复的工作.比如在不同的工作场所需要切换不同的ip:比如有时需要对一堆文件按1~n进行重命名:再比如我们需要删除一大堆文件,这些文件名字都差不多, ...

  3. Node.js:fs文件系统模块

    fs文件系统模块,这是一个非常重要的模块,对文件的操作都基于它.该模块的所有方法都有同步和异步两种方式,下面便介绍一下该模块的使用. 1.检测当前进程对文件的权限 使用fs.access(path[, ...

  4. Java Collection知识总结

    首先说说java中常用的集合容器:ArrayList,LinkedList,Vector,HashMap,Hashtable,HashSet,TreeSet.[就个人认为] java集合容器本人理解为 ...

  5. 解决Jquery Kendo.xxx is not a function 的方法

    不知道大家遇到过没有,要同时间使用Telerick 和Kendo的时候 这个问题搞了我好多天,其实解决方法很简单,就是在LAYOUT里面先写TELERIK的注册脚本, 再写KENDO的. @(Html ...

  6. Restful Api 最佳实践

    Web APIs has become an very important topic in the last year. We at M-Way Solutions are working ever ...

  7. 我为什么要自己编译openjdk8以及那些坑

    我为什么要自己编译openjdk8以及那些坑 这是笔者第二次编译openjdk, 第一次编译的是openjdk7,那么好多人会好奇,为什么要自己编译openjdk呢,官方不是已经发布了安装包了么? 要 ...

  8. 怎样把win7系统下的屏幕设置成护眼的非常柔和的豆沙绿色?

    经常面对电脑会导致眼睛过度疲劳,白色对眼睛的刺激是最大的,所以,最好不要用白色做电脑背景色 设置方法如下: 在桌面点右键选"个性化",接着点主窗口底部的"窗口颜色&quo ...

  9. Win10 UWP开发系列:使用VS2015 Update2+ionic开发第一个Cordova App

    安装VS2015 Update2的过程是非常曲折的.还好经过不懈的努力,终于折腾成功了. 如果开发Cordova项目的话,推荐大家用一下ionic这个框架,效果还不错.对于Cordova.PhoneG ...

  10. [Asp.net 5] Caching-缓存架构与源码分析

    首先奉献caching的开源地址[微软源码] 1.工程架构 为了提高程序效率,我们经常将一些不频繁修改,但是使用了还很大的数据进行缓存.尤其是互联网产品,缓存可以说是提升效率优化第一利器.微软为我们实 ...