密码协议实验——SIGMMA协议

密码协议实验——SIGMMA协议

最近密码学做了很多密码协议的实验,主要是在visual stdio 2019环境下运用miracl库、openssl库实现密码协议,利用socket实现通信。本文记录从配置环境开始,实现SIGMMA协议的每一步。
(马上要期末考试了,其他实验先鸽了)

实验1 DH认证密钥交换协议实现

SIGMA协议

原理在这里插入图片描述
步骤
1.配置miracl和openssl库环境

配置miracl库环境

  1. 配置有点麻烦,首先是下载源码,贴一个miracl源码地址

链接:https://pan.baidu.com/s/17DXQYBwdNLyiIYq-GVjFdw
提取码:nht3

  1. 然后将源码编译生成静态链接库有点麻烦,可以直接用别人生成好的,贴一个生成好的静态库链接。(如果直接用别人生成好的可以不用下载源码)

链接:https://pan.baidu.com/s/1mVyfiZ-6LeUjW9S-WXf_8A
提取码:bvlz

然后将四个文件miracl.lib、miracl.pdb、miracl.h 和mirdef.h复制到项目文件夹下,并导入项目(右键项目->添加->现有项)

在这里插入图片描述

  1. 接下来配置环境:(右键项目->添加->属性)
  • VC++目录->包含目录、库目录

包含目录中选择miracl源码中的include文件夹地址,库目录中选择miracl源码中的lib文件夹地址

在这里插入图片描述

  • 链接器->常规->附加库目录:添加项目地址
    在这里插入图片描述

  • 链接器->输入->附加依赖项:输入miracl.lib

在这里插入图片描述

  • C/C++目录->附件包含目录:选择包含目录中选择miracl源码中的include文件夹地址
    在这里插入图片描述

注意:C/C++这一选项必须要在源文件中有.c/.cpp文件中的时候才会出现

注意:由于miracl库是由c编写的,如果要在c++文件中调用,需要加以下代码

extern "C"
{
	#include "miracl.h"
	#include "mirdef.h"
}

4.项目重新生成

配置openssl库环境

参考链接:<(15条消息) VS中OpenSSL环境配置示例_huang714的专栏-CSDN博客_vs配置openssl>

  1. 可选择类似于miracl库的源码编译,建议直接下载编译好的类库,贴一个地址

    链接:https://pan.baidu.com/s/1Xw_mYFSDW59JGnkCvGUr2g
    提取码:hsga

  2. 配置环境

  • VC++目录->包含目录、库目录

在这里插入图片描述

  • 链接器->输入->附加依赖项:输入ssleay.lib、libeay.lib

在这里插入图片描述

  1. 将openssl文件夹中的libeay32.dll和ssleay32.dll文件项目所在文件夹中

在这里插入图片描述

  1. 项目重新生成
2.利用miral库实现以下功能
  • 生成大素数
big g = mirvar(0);   //循环群的生成元
big p = mirvar(0);   //大素数
big q1 = mirvar(0);  //利用q1辅助生成p

bigdig(150, 10, q1);//生成一个150位的随机数,512bit左右 200位660bit左右 300位1000bit左右
nxsafeprime(0, 0, q1, p);//生成一个比q大的安全素数P
printf("生成的大素数为:\n");
printf("p = ");
cotnum(p, stdout);
  • 计算Alice、Bob密钥交换协议中的使用的公钥
big x1 = mirvar(0);  //Alice的私钥
big x2 = mirvar(0);  //Bob的私钥
big X1 = mirvar(0);  //Alice的公钥
big X2 = mirvar(0);  //Bob的公钥

copy(get_generator(p), g);
printf("循环群Gp的一个生成元为: \n");
printf("g=");
cotnum(g, stdout);

//计算各自公钥
convert(134, x1); 
convert(2374, x2);
powmod(g, x1, p, X1);  //计算Alice公钥
powmod(g, x2, p, X2);  //计算Bob公钥
cout << "Alice、Bob公钥(g^x)分别为" << endl;
cotnum(X1, stdout);
cotnum(X2, stdout);
  • 寻找循环群的生成元

    寻找生成元是一个困难问题,难以找到一个循环群的所有生成元,可用遍历的方法,找到其中一个生成元。

    原根的判定方法:
    g 2 m o d p ! = 1 a n d g q m o d p ! = 1 a n d g p − 1 m o d p = 1 p = 2 q ; g^2 mod p!=1 \quad and\quad g^q mod p !=1 \quad and \quad g^{p-1} mod p=1\\ p=2q; g2modp!=1andgqmodp!=1andgp1modp=1p=2q;
    生成原根源程序:generatorg.cpp

    extern "C"
    {
    #include "miracl.h"
    #include "mirdef.h"
    }
    
    #include<stdio.h>
    #include<math.h>
    #include <stdlib.h>
    #include <conio.h>
    #include "miracl.h"
    #include "generatorg.h"
    
    big get_generator(big p)  //得到p的一个原根
    {
    	big one = mirvar(1);
    	big two = mirvar(2);
    	big g = mirvar(0); //原根
    	big r1 = mirvar(0);
    	big r2 = mirvar(0);
    	big q = mirvar(0);
    	big temp_up = mirvar(0);
    	decr(p, 1, temp_up); //temp_up=p-1
    	fdiv(temp_up, two, q); //q=
    	while (TRUE) {
    		bigrand(temp_up, g); // 随机生成一个小于p-1的数
    		powmod(g, two, p, r1);
    		powmod(g, q, p, r2);
    		if (mr_compare(r1, one) && mr_compare(r2, one)) {  //mr_compare(big x,big y): x=y时,返回0  即g^2=1 mod p && g^(p-1/2)=1 mod p
    			return g;
    		}
    	}
    }
    

    头文件:generator.h

    #pragma once
    #include<stdio.h>
    #include<math.h>
    #include "miracl.h"
    #include <stdlib.h>
    #include <conio.h>
    
    big get_generator(big p);
    

附:miracl常用库函数

参考链接https://blog.csdn.net/shuilan0066/article/details/8520337

详见miracl库中的manual.doc文档

函数原型函数功能
miracl *mirsys(int nd, int nb)初始化MIRACL系统,nd为位数,nb为进制
void mirkill(big x)释放内存大数所占的内存
void mirexit()清除MIRACL系统,释放所有内部变量
void absol(big x,big y)求绝对值
void add(big x,big y,big z)求大数加法 z=x+y
void bigbits(int n,big x)随机产生一个n位的大数
void bigdig(int n, int b, big x)产生一个指定长度的进制的随机数,n为长度,b为进制
void bigrand(big w, big x)产生一个小于w的大数随机数
int cinstr(big x, char*s)将大数字符串转换成大数
int cotstr(big x, char *s)大数根据其进制转换成一个字符串,返回字符串长度
int mr_compare(big x,big y)比较两个数大小: x>y时返回+1, x=y时返回0, x<y时返回-1
void convert(int n, big x)将一个整数n转换成一个大数x
void copy(big x, big y)将一个大数赋值给另一个大数
void incr(big x, int n, big z)一个大数加上一个整数 z=x+n
void decr(big x, int n, big z)一个大数减去一个整数, z=x-n
void divide(big x, big y, big z)两个大数相除,z=x/y; x=x mod y
void multiply(big x, big y, big z)两个大数相乘,z=x.y
void fft_mult(big x, big y, big z)使用Fast Fourier算法计算两个大数乘积,z=x.y
BOOL subdivisible(big x, int n)测试n能否整除x
BOOL divisible(big x, big y)测试大数x能否整除大数y
void premult(big x, int n, big z)一个大数乘以一个整数,z=n.x
int subdiv(big x, int n, big z)一个大数除以一个整数,z=x/n,返回余数
intigcd(int x, int y)返回两个整数的最大公约数
int egcd(bigx, big y, big z)计算两个大数的最大公约数,z=gcd(x,y)
int xgcd(bigx, big y, big xd, big yd, big z)计算两个大数的扩展最大公约数,也可以用来计算模逆
void negify(big x, big y)大数取负号
int numdig(big x)返回大数x中数字的个数
void expb2(int n, big x)计算2的n次方的大数
void expint(intb, int n, big x)计算b的n次方的大数
unsigned int invers(unsigned int x, unsigned int y)计算两个无符号整数(要求互素)的模逆,返回x-1 mod y
BOOL isprime(bigx)判断一个大数是否为素数
void powmod(big x, big y,big z, big w)模幂运算, w = x y m o d z w=x^y mod z w=xymodz
void sftbit(big x, int n,big z)将一个大数左移或右移n位,n为正数时左移,负数时右移
3.利用openssl库实现以下功能

参考链接:<C/C++使用openssl进行摘要和加密解密(md5, sha256, des, rsa) - findumars - 博客园 (cnblogs.com)>

  • 对身份信息进行摘要(以md5为例)

SIGMA协议中,需要对Alice、Bob的身份信息(姓名、身份证号等)进行摘要,

生成摘要函数源程序:mac.cpp

//利用openssl 生成md5摘要

#define _CRT_SECURE_NO_WARNINGS

#include <iostream>    
#include <cassert>  
#include <string>    
#include <vector>    
#include "openssl/md5.h"       
#include "openssl/pem.h" 
#include "mac.h"

using namespace std;

void md5(string& srcStr, string& encodedStr, string& encodedHexStr)  //传入明文、摘要字符、摘要字符、摘要字符串
{
    // 调用md5哈希    
    unsigned char mdStr[33] = { 0 };
    MD5((const unsigned char*)srcStr.c_str(), srcStr.length(), mdStr);//c_str()函数返回一个指向正规C字符串的指针常量, 内容与本string串相同,为了与c兼容

    // 哈希后的字符串    
    encodedStr = string((const char*)mdStr);
    // 哈希后的十六进制串 32字节    
    char buf[65] = { 0 };
    char tmp[3] = { 0 };
    for (int i = 0; i < 32; i++)
    {
        sprintf(tmp, "%02x", mdStr[i]);  //sprintf() 格式化输出函数(图形)
        //x 表示以十六进制形式输出,02 表示不足两位, 前面补0输出,如果超过两位,则以实际输出
        strcat(buf, tmp);
    }
    buf[32] = '\0'; // 后面都是0,从32字节截断    
    encodedHexStr = string(buf);
}

生成摘要函数头文件:mac.h

#pragma once
#include <iostream>    
#include <cassert>  
#include <string>    
#include <vector>    
#include "openssl/md5.h"       
#include "openssl/pem.h" 

using namespace std;

void md5(string& srcStr, string& encodedStr, string& encodedHexStr);
  • 对公钥 ( g x , g y ) (g^x,g^y) (gx,gy)进行签名并验证

    对公钥签名源程序:sign.cpp

#include<openssl/pem.h>
#include<openssl/ssl.h>
#include<openssl/rsa.h>
#include<openssl/evp.h>
#include<openssl/bio.h>
#include<openssl/err.h>
#include <stdio.h>
#include<iostream>
#include<fstream>
#include "sign.h"

using namespace std;

//把字符串写成public.pem文件
int createPublicFile(const char* file, const string& pubstr)
{
    if (pubstr.empty())
    {
        printf("public key read error\n");
        return (-1);
    }
    int len = pubstr.length();
    string tmp = pubstr;
    for (int i = 64; i < len; i += 64)
    {
        if (tmp[i] != '\n')
        {
            tmp.insert(i, "\n");
        }
        i++;
    }
    tmp.insert(0, "-----BEGIN PUBLIC KEY-----\n");
    tmp.append("\n-----END PUBLIC KEY-----\n");

    //写文件
    ofstream fout(file);
    fout << tmp;

    return (0);
}

//把字符串写成private.pem文件
int createPrivateFile(char* file, const string& pristr)
{
    if (pristr.empty())
    {
        printf("public key read error\n");
        return (-1);
    }
    int len = pristr.length();
    string tmp = pristr;
    for (int i = 64; i < len; i += 64)
    {
        if (tmp[i] != '\n')
        {
            tmp.insert(i, "\n");
        }
        i++;
    }
    tmp.insert(0, "-----BEGIN RSA PRIVATE KEY-----\n");
    tmp.append("-----END RSA PRIVATE KEY-----\n");

    //写文件
    ofstream fout(file);
    fout << tmp;

    return (0);
}

//读取密钥
RSA* createRSA(unsigned char* key, int publi)
{
    RSA* rsa = NULL;
    BIO* keybio;
    keybio = BIO_new_mem_buf(key, -1);
    if (keybio == NULL)
    {
        printf("Failed to create key BIO\n");
        return 0;
    }
    if (publi)
        rsa = PEM_read_bio_RSA_PUBKEY(keybio, &rsa, NULL, NULL);
    else
        rsa = PEM_read_bio_RSAPrivateKey(keybio, &rsa, NULL, NULL);
    if (rsa == NULL)
        printf("Failed to create RSA\n");

    return rsa;
}

//私钥签名
int private_sign(const unsigned char* in_str, unsigned int in_str_len, unsigned char* outret, unsigned int* outlen, unsigned char* key)
{
    RSA* rsa = createRSA(key, 0);
    int result = RSA_sign(NID_sha1, in_str, in_str_len, outret, outlen, rsa);
    if (result != 1)
    {
        printf("sign error\n");
        return -1;
    }
    return result;
}

//公钥验签
int public_verify(const unsigned char* in_str, unsigned int in_len, unsigned char* outret, unsigned int outlen, unsigned char* key)
{
    RSA* rsa = createRSA(key, 1);
    int result = RSA_verify(NID_sha1, in_str, in_len, outret, outlen, rsa);
    if (result != 1)
    {
        printf("verify error\n");
        return -1;
    }

    return result;
}

对公钥签名头文件:sign.h

#pragma once

#include<openssl/pem.h>
#include<openssl/ssl.h>
#include<openssl/rsa.h>
#include<openssl/evp.h>
#include<openssl/bio.h>
#include<openssl/err.h>
#include <stdio.h>
#include<iostream>
#include<fstream>

using namespace std;

int createPublicFile(const char* file, const string& pubstr);
int createPrivateFile(char* file, const string& pristr);
RSA* createRSA(unsigned char* key, int publi);
int private_sign(const unsigned char* in_str, unsigned int in_str_len, unsigned char* outret, unsigned int* outlen, unsigned char* key);
int public_verify(const unsigned char* in_str, unsigned int in_len, unsigned char* outret, unsigned int outlen, unsigned char* key);

主程序:main.cpp

#define _CRT_SECURE_NO_WARNINGS
extern "C"
{
	#include "miracl.h"
	#include "mirdef.h"
}

#include <iostream>
#include <cstdio>
#include <string.h>
#include "miracl.h"
#include "mirdef.h"
#include "generatorg.h"
#include "mac.h"
#include "sign.h"

using namespace std;


//ALice公钥
char publicKey1[] = "-----BEGIN PUBLIC KEY-----\n"\
"MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAy8Dbv8prpJ/0kKhlGeJY\n"\
"ozo2t60EG8L0561g13R29LvMR5hyvGZlGJpmn65+A4xHXInJYiPuKzrKUnApeLZ+\n"\
"vw1HocOAZtWK0z3r26uA8kQYOKX9Qt/DbCdvsF9wF8gRK0ptx9M6R13NvBxvVQAp\n"\
"fc9jB9nTzphOgM4JiEYvlV8FLhg9yZovMYd6Wwf3aoXK891VQxTr/kQYoq1Yp+68\n"\
"i6T4nNq7NWC+UNVjQHxNQMQMzU6lWCX8zyg3yH88OAQkUXIXKfQ+NkvYQ1cxaMoV\n"\
"PpY72+eVthKzpMeyHkBn7ciumk5qgLTEJAfWZpe4f4eFZj/Rc8Y8Jj2IS5kVPjUy\n"\
"wQIDAQAB\n"\
"-----END PUBLIC KEY-----\n";

//Alice私钥
char privateKey1[] = "-----BEGIN RSA PRIVATE KEY-----\n"\
"MIIEowIBAAKCAQEAy8Dbv8prpJ/0kKhlGeJYozo2t60EG8L0561g13R29LvMR5hy\n"\
"vGZlGJpmn65+A4xHXInJYiPuKzrKUnApeLZ+vw1HocOAZtWK0z3r26uA8kQYOKX9\n"\
"Qt/DbCdvsF9wF8gRK0ptx9M6R13NvBxvVQApfc9jB9nTzphOgM4JiEYvlV8FLhg9\n"\
"yZovMYd6Wwf3aoXK891VQxTr/kQYoq1Yp+68i6T4nNq7NWC+UNVjQHxNQMQMzU6l\n"\
"WCX8zyg3yH88OAQkUXIXKfQ+NkvYQ1cxaMoVPpY72+eVthKzpMeyHkBn7ciumk5q\n"\
"gLTEJAfWZpe4f4eFZj/Rc8Y8Jj2IS5kVPjUywQIDAQABAoIBADhg1u1Mv1hAAlX8\n"\
"omz1Gn2f4AAW2aos2cM5UDCNw1SYmj+9SRIkaxjRsE/C4o9sw1oxrg1/z6kajV0e\n"\
"N/t008FdlVKHXAIYWF93JMoVvIpMmT8jft6AN/y3NMpivgt2inmmEJZYNioFJKZG\n"\
"X+/vKYvsVISZm2fw8NfnKvAQK55yu+GRWBZGOeS9K+LbYvOwcrjKhHz66m4bedKd\n"\
"gVAix6NE5iwmjNXktSQlJMCjbtdNXg/xo1/G4kG2p/MO1HLcKfe1N5FgBiXj3Qjl\n"\
"vgvjJZkh1as2KTgaPOBqZaP03738VnYg23ISyvfT/teArVGtxrmFP7939EvJFKpF\n"\
"1wTxuDkCgYEA7t0DR37zt+dEJy+5vm7zSmN97VenwQJFWMiulkHGa0yU3lLasxxu\n"\
"m0oUtndIjenIvSx6t3Y+agK2F3EPbb0AZ5wZ1p1IXs4vktgeQwSSBdqcM8LZFDvZ\n"\
"uPboQnJoRdIkd62XnP5ekIEIBAfOp8v2wFpSfE7nNH2u4CpAXNSF9HsCgYEA2l8D\n"\
"JrDE5m9Kkn+J4l+AdGfeBL1igPF3DnuPoV67BpgiaAgI4h25UJzXiDKKoa706S0D\n"\
"4XB74zOLX11MaGPMIdhlG+SgeQfNoC5lE4ZWXNyESJH1SVgRGT9nBC2vtL6bxCVV\n"\
"WBkTeC5D6c/QXcai6yw6OYyNNdp0uznKURe1xvMCgYBVYYcEjWqMuAvyferFGV+5\n"\
"nWqr5gM+yJMFM2bEqupD/HHSLoeiMm2O8KIKvwSeRYzNohKTdZ7FwgZYxr8fGMoG\n"\
"PxQ1VK9DxCvZL4tRpVaU5Rmknud9hg9DQG6xIbgIDR+f79sb8QjYWmcFGc1SyWOA\n"\
"SkjlykZ2yt4xnqi3BfiD9QKBgGqLgRYXmXp1QoVIBRaWUi55nzHg1XbkWZqPXvz1\n"\
"I3uMLv1jLjJlHk3euKqTPmC05HoApKwSHeA0/gOBmg404xyAYJTDcCidTg6hlF96\n"\
"ZBja3xApZuxqM62F6dV4FQqzFX0WWhWp5n301N33r0qR6FumMKJzmVJ1TA8tmzEF\n"\
"yINRAoGBAJqioYs8rK6eXzA8ywYLjqTLu/yQSLBn/4ta36K8DyCoLNlNxSuox+A5\n"\
"w6z2vEfRVQDq4Hm4vBzjdi3QfYLNkTiTqLcvgWZ+eX44ogXtdTDO7c+GeMKWz4XX\n"\
"uJSUVL5+CVjKLjZEJ6Qc2WZLl94xSwL71E41H4YciVnSCQxVc4Jw\n"\
"-----END RSA PRIVATE KEY-----\n";


int main()
{ 
	miracl* mips = mirsys(2400, 10);

	big g = mirvar(0);   //循环群的生成元
	big p = mirvar(0);   //大素数
	big q1 = mirvar(0);  //利用q1辅助生成p
	big x1 = mirvar(0);  //Alice的私钥
	big x2 = mirvar(0);  //Bob的私钥
	big X1 = mirvar(0);  //Alice的公钥
	big X2 = mirvar(0);  //Bob的公钥

	bigdig(100, 10, q1);//生成一个150位的随机数,512bit左右 200位660bit左右 300位1000bit左右
	nxsafeprime(0, 0, q1, p);//生成一个比q大的安全素数P
	printf("生成的大素数为:\n");
	printf("p = ");
	cotnum(p, stdout);

	copy(get_generator(p), g);
	printf("循环群Gp的一个生成元为: \n");
	printf("g=");
	cotnum(g, stdout);

	//计算各自公钥
	convert(134, x1); 
	convert(2374, x2);
	powmod(g, x1, p, X1);  //计算Alice公钥
	powmod(g, x2, p, X2);  //计算Bob公钥
	cout << "Alice、Bob公钥(g^x)分别为" << endl;
	cotnum(X1, stdout);
	cotnum(X2, stdout);

	//对Alice、Bob各自身份的身份信息进行加密(以名字为例)
	string srcText1 = "Alice";
	string srcText2 = "Bob";
	string encryptText1;
	string encryptHexText1;
	string encryptText2;
	string encryptHexText2;

	cout << "===Alice、Bob的身份信息分别为 ===" << endl;
	cout << srcText1 <<" "<<srcText2<<endl;
  
	cout << "===对Alice、Bob的身份信息进行md5摘要结果为 ===" << endl;
	md5(srcText1, encryptText1, encryptHexText1);
	md5(srcText2, encryptText2, encryptHexText2);
	cout << "Alice身份信息摘要字符: " << encryptText1<< endl;
	cout << "Alice身份信息摘要串(16进制32字节): " << encryptHexText1 << endl;
	cout << "Bob身份信息摘要字符: " << encryptText2 << endl;
	cout << "Bob身份信息摘要串(16进制32字节): " << encryptHexText2<< endl;

	//签名
	char gx[2048],gy[1024];
	cotstr(X1, gx);
	cotstr(X2, gy);
	strcat(gx, gy);
	printf("%s\n", gx);
	
	cout << strlen(gx) << endl;

	unsigned char signret[4098] = {};
	unsigned int siglen;

	cout << "===私钥签名公钥认证===" << endl;
	int ret = private_sign((const unsigned char*)gx, strlen(gx), signret, &siglen, (unsigned char*)privateKey1);
	if (ret)	cout << "签名成功" << endl;
	else cout << "签名失败" << endl;
	ret = public_verify((const unsigned char*)gx, strlen(gx), signret, siglen, (unsigned char*)publicKey1);
	if (ret)	cout << "认证成功" << endl;
	else cout << "认证失败" << endl;
	
	return 0;
}

运行结果
在这里插入图片描述

4.利用socket实现解法双方通信

通信部分是小组其他成员写的,就直接加在main函数里了。

WSADATA wsaData;
	WSAStartup(MAKEWORD(2, 2), &wsaData);

	//创建套接字
	SOCKET clntSock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);

	//向服务器发送消息,处理地址等信息
	sockaddr_in sockAddr;
	memset(&sockAddr, 0, sizeof(sockAddr));			//每个字节都用0填充
	sockAddr.sin_family = PF_INET;
	sockAddr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
	sockAddr.sin_port = htons(8888);
	connect(clntSock, (SOCKADDR*)&sockAddr, sizeof(SOCKADDR));
	//接收服务器消息
	char szBuffer[0xffff] = { 0 };
	send(clntSock, ga, strlen(ga) + sizeof(char), NULL);
	recv(clntSock, szBuffer, 0xffff, NULL);//定义一次接收的缓存数组的大小要用16进制
	//输出接收到的数据
//	cout << "gy:" << szBuffer << endl;
	
	send(clntSock, unit, strlen(unit) + sizeof(char), NULL);									   	   
	//szBuffer[0xffff] = { 0 };
	recv(clntSock, szBuffer, 0xffff, NULL);
	char* pstring;
	char message[4][1024];
	pstring = strtok(szBuffer, "|");
	cout << "接收到的Bob的信息:" <<endl;
	int i = 0;
	while (pstring)
	{
		strcpy(message[i], pstring);
		i++;
		//printf("%s\n", pstring);
		pstring = strtok(NULL, "|");
	}
	printf("Bob的公钥gy:%s\n", message[0]);
	printf("Bob的身份:%s\n", message[1]);
	printf("Bob的签名:%s\n", message[2]);
	printf("Bob的摘要:%s\n", message[3]);
	//szBuffer[0xffff] = { 0 };
	send(clntSock, MACA, strlen(MACA) + sizeof(char), NULL);
	recv(clntSock, szBuffer, 0xffff, NULL);
	//cout << "BobMac签名:" << szBuffer << endl;
	//关闭套接字
	closesocket(clntSock);
	//终止dll
	WSACleanup();

运行结果
在这里插入图片描述

评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值