这是我从网上找来改好的,需要添加 include 和 lib 路径
需要自己手动生成 pem 文件,在注释里面有命行,自己动手。
1 #define WIN32_LEAN_AND_MEAN 2 3 #include <stdio.h> 4 #include <stdlib.h> 5 #include <errno.h> 6 #include <string.h> 7 #include <sys/types.h> 8 #include <Windows.h> 9 #include <WinSock2.h> 10 #include <MSWSock.h> 11 #include <WS2tcpip.h> 12 #include <openssl/ssl.h> 13 #include <openssl/err.h> 14 #pragma comment(lib, "ws2_32.lib") 15 #pragma comment(lib, "libssl.lib") 16 #pragma comment(lib, "libcrypto.lib") 17 #pragma comment(lib, "Crypt32.lib") 18 19 // openssl 生成公钥和私钥的方法: 20 // openssl genrsa -out privkey.pem 2048 21 // openssl req -config openssl.cnf -new -x509 -key privkey.pem -out cacert.pem -days 1095 22 23 #define MAXBUF 1024 24 25 /************关于本文档********************************************* 26 ************filename: ssl-server.c 27 *************purpose: 演示利用 OpenSSL 库进行基于 IP层的 SSL 加密通讯的方法,这是服务器端例子 28 **********************************************************************************/ 29 30 #define bzero ZeroMemory 31 #define close closesocket 32 33 SSL_CTX *ctx; 34 bool InitSslAll(char* publicPem, char* privatePem) 35 { 36 /* SSL 库初始化 */ 37 SSL_library_init(); 38 39 /* 载入所有 SSL 算法 */ 40 OpenSSL_add_all_algorithms(); 41 42 /* 载入所有 SSL 错误消息 */ 43 SSL_load_error_strings(); 44 45 /* 以 SSL V2 和 V3 标准兼容方式产生一个 SSL_CTX ,即 SSL Content Text */ 46 ctx = SSL_CTX_new(SSLv23_server_method()); 47 48 /* 也可以用 SSLv2_server_method() 或 SSLv3_server_method() 单独表示 V2 或 V3标准 */ 49 if (ctx == NULL) { 50 ERR_print_errors_fp(stdout); 51 return false; 52 } 53 54 /* 载入用户的数字证书, 此证书用来发送给客户端。 证书里包含有公钥 */ 55 if (SSL_CTX_use_certificate_file(ctx, publicPem, SSL_FILETYPE_PEM) <= 0) 56 { 57 ERR_print_errors_fp(stdout); 58 return false; 59 } 60 61 /* 载入用户私钥 */ 62 if (SSL_CTX_use_PrivateKey_file(ctx, privatePem, SSL_FILETYPE_PEM) <= 0) 63 { 64 ERR_print_errors_fp(stdout); 65 return false; 66 } 67 68 /* 检查用户私钥是否正确 */ 69 if (!SSL_CTX_check_private_key(ctx)) 70 { 71 ERR_print_errors_fp(stdout); 72 return false; 73 } 74 return true; 75 } 76 77 int main(int argc, char **argv){ 78 SOCKET sockfd, new_fd; 79 socklen_t len; 80 struct sockaddr_in my_addr, their_addr; 81 unsigned int myport, lisnum; 82 char buf[MAXBUF + 1]; 83 84 if (argv[1]) 85 myport = atoi(argv[1]); 86 else 87 myport = 7838; 88 if (argv[2]) 89 lisnum = atoi(argv[2]); 90 else 91 lisnum = 2; 92 93 InitSslAll(argv[4], argv[5]); 94 95 WSADATA wsaData; 96 int iResult = 0; 97 iResult = WSAStartup(MAKEWORD(2, 2), &wsaData); 98 if (iResult != NO_ERROR) { 99 wprintf(L"Error at WSAStartup() "); 100 return 1; 101 } 102 103 /* 开启一个 socket 监听 */ 104 if ((sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1) 105 { 106 perror("socket"); 107 exit(1); 108 } else 109 printf("socket created "); 110 111 bzero(&my_addr, sizeof(my_addr)); 112 my_addr.sin_family = PF_INET; 113 my_addr.sin_port = htons(myport); 114 if (argv[3]) 115 inet_pton(AF_INET, argv[3], &my_addr.sin_addr.s_addr); 116 else 117 my_addr.sin_addr.s_addr = INADDR_ANY; 118 119 if (bind(sockfd, (struct sockaddr *)&my_addr, sizeof(struct sockaddr)) == -1) 120 { 121 printf("bind error:%d", WSAGetLastError()); 122 exit(1); 123 } 124 else 125 printf("binded "); 126 127 if (listen(sockfd, lisnum) == -1) 128 { 129 printf("listen error:%d", WSAGetLastError()); 130 exit(1); 131 } else 132 printf("begin listen "); 133 134 while (1) 135 { 136 SSL *ssl; 137 len = sizeof(struct sockaddr); 138 139 /* 等待客户端连上来 */ 140 if ((new_fd =accept(sockfd, (struct sockaddr *) &their_addr,&len)) == -1) 141 { 142 printf("accept error:%d", WSAGetLastError()); 143 exit(errno); 144 } 145 else 146 { 147 char addr[64] = { 0 }; 148 149 inet_ntop(AF_INET, &their_addr.sin_addr, addr, 64); 150 printf("server: got connection from %s, port %d, socket %d " 151 , addr, ntohs(their_addr.sin_port), new_fd); 152 } 153 154 155 /* 基于 ctx 产生一个新的 SSL */ 156 ssl = SSL_new(ctx); 157 158 /* 将连接用户的 socket 加入到 SSL */ 159 160 SSL_set_fd(ssl, new_fd); 161 162 /* 建立 SSL 连接 */ 163 164 if (SSL_accept(ssl) == -1) 165 { 166 perror("accept"); 167 close(new_fd); 168 break; 169 } 170 171 /* 开始处理每个新连接上的数据收发 */ 172 173 bzero(buf, MAXBUF + 1); 174 strcpy_s(buf, MAXBUF, "server->client"); 175 176 /* 发消息给客户端 */ 177 len = SSL_write(ssl, buf, strlen(buf)); 178 if (len <= 0) { 179 char err[256] = { 0 }; 180 strerror_s(err, errno); 181 printf("消息'%s'发送失败!错误代码是%d,错误信息是'%s' ", 182 buf, errno, err); 183 goto finish; 184 } else 185 printf("消息'%s'发送成功,共发送了%d个字节! ", 186 buf, len); 187 bzero(buf, MAXBUF + 1); 188 189 /* 接收客户端的消息 */ 190 len = SSL_read(ssl, buf, MAXBUF); 191 if (len > 0) 192 printf("接收消息成功:'%s',共%d个字节的数据 ", 193 buf, len); 194 else 195 { 196 char err[256] = { 0 }; 197 strerror_s(err, errno); 198 printf("消息接收失败!错误代码是%d,错误信息是'%s' ", 199 errno, err); 200 } 201 202 203 /* 处理每个新连接上的数据收发结束 */ 204 finish: 205 206 /* 关闭 SSL 连接 */ 207 SSL_shutdown(ssl); 208 /* 释放 SSL */ 209 SSL_free(ssl); 210 211 /* 关闭 socket */ 212 213 close(new_fd); 214 } 215 216 /* 关闭监听的 socket */ 217 218 close(sockfd); 219 220 /* 释放 CTX */ 221 222 SSL_CTX_free(ctx); 223 224 return 0; 225 226 } 227 228