一、C++模拟TCP滑动窗口传输

此程序是用C++进行模拟tcp的“滑动窗口”操作,具体操作如下:
1、首先在提示下发送端输入发送信息和窗口大小
2、调用tcp()函数进行将发送端信息发送给接收端操作
3、具体具体原理如下:
1)发送端每次将窗口大小的信息传给接收端
2)接收端对收到信息进行存储,并发送ack确认给发送端
示例:
1、输入“qwertyuiopasdfghklzxc”作为发送信息
在这里插入图片描述
2、输入“5”作为窗口大小
在这里插入图片描述
4、输出tcp传输的过程
在这里插入图片描述
代码如下:

#include <iostream>
#include <string.h>
using namespace std;

void print(char(*m)[30], char *n, int s, int l) {
	int i;
	cout << "发送端如下↓" << endl;
	cout << "信息队列:";
	for (i = 0; i < l; i++)
		cout << m[0][i] << ' ';
	cout << endl << " ack接收:";
	for (i = 0; i < l; i++)
		cout << m[1][i] << ' ';
	cout << endl << endl << "接收端如下↓" << endl;
	cout << "信息队列:";
	for (i = 0; i < l; i++)
		cout << n[i] << ' ';
	cout << endl << endl;
}

int tcp(char(*m)[30], char *n, int s, int l)
{
	char ack[7] = "123456";
	int i, j, k;
	j = i = 0;
	k = 1;
	cout << "-------------------------------------------------------" << endl;
	cout << "发送信息为:" << m[0] << endl;
	cout << "发送信息长度为:" << l << endl;
	cout << "发送窗口大小为:" << s << endl;
	while (i < l) {
		for (; j < s && i < l; i++) {
			n[i] = m[0][i];
			m[1][i] = ack[j++];
		}
		j = 0;
		cout << "-------------------------------------------------------" << endl;
		cout << "第" << k << "次传输结果:" << endl;
		print(m, n, s, l);
		k++;
	}
	return 0;
}
int main()
{
	int l, s;   ///l表示发送信息的长度,
	char m[2][30]; ///用二维字符组表示发送端发送信息内容与接收到的ack确认信息
	char n[30];    ///用字符串表示接收端接收信息
	cout << "请输入发送端信息:" << endl;
	cin >> m[0];
	l = (int)strlen(m[0]);
	while (1) {
		cout << "请输入窗口大小(小于等于6):" << endl;
		cin >> s;
		if (s <= 5)
			break;
	}
	for (int j = 0; j < l; j++)
	{
		n[j] = '\0';
		m[1][j] = '\0';
	}
	tcp(m, n, s, l);
	cout << endl;
	system("pause");
	return 0;
}

二、在Matlab中读取采集到的imu数据(txt格式),并绘图显示

参考:http://t.csdn.cn/qcXYo

%本例程读取的数据是惯导数据(三轴陀螺仪、三轴加速度计),源文件为txt格式,在matlab中读取6种数据并作图显示
fs=25.6;                    %采样频率
T=1/fs;                     %采样周期
data=load('data8.txt');     %加载txt文件
save('data.mat','data');    %将读取到的数据存入mat格式文件
length=size(data);          %求得数据长度,这里length是一个包含两个数据的向量,第一个数据是data矩阵的行数,第二个数据是data矩阵的列数
time=length(1)/fs;          %求出数据采集时间的总长度,用于横坐标显示
t=(1:length(1))/fs;         %求得步长

figure(1);
gx=data(:,1);%获取第一列数据
subplot(3,1,1);
plot(t,gx);axis([0 time -300 300]);title('gx');xlabel('时间(s)');ylabel('角速度(°/s)');
gy=data(:,2);%获取第二列数据
subplot(3,1,2);
plot(t,gy);axis([0 time -300 300]);title('gy');xlabel('时间(s)');ylabel('角速度(°/s)');
gz=data(:,3);%获取第三列数据
subplot(3,1,3);
plot(t,gz);axis([0 time -300 300]);title('gz');xlabel('时间(s)');ylabel('角速度(°/s)');

figure(2);
ax=data(:,4);%获取第四列数据
subplot(3,1,1);
plot(t,ax);axis([0 time -2 2]);title('ax');xlabel('时间(s)');ylabel('加速度(g/s^2)');
ay=data(:,5);%获取第五列数据
subplot(3,1,2);
plot(t,ay);axis([0 time -2 2]);title('ay');xlabel('时间(s)');ylabel('加速度(g/s^2)');
az=data(:,6);%获取第六列数据
subplot(3,1,3);
plot(t,az);axis([0 time -2 2]);title('az');xlabel('时间(s)');ylabel('加速度(g/s^2)');

data数据在 H:\code-practice\matlab_practice\matlab中读取txt数据并绘图显示
在这里插入图片描述

三、C++产生随机数的几种方法

使用cstdlib库
C++11之前,C和C++都用相同的方法来产生随机数(伪随机数),即rand()函数,用法如下:

1)使用srand()撒一个种子
功能:初始化随机数发生器

用法:void srand(unsigned int seed)

2)使用rand()产生随机数
功能:随机数发生器

用法:int rand(void)

3)控制随机数范围

要取得 [a,b) 的随机整数,使用 (rand() % (b-a))+ a;
要取得 [a,b] 的随机整数,使用 (rand() % (b-a+1))+ a;
要取得 (a,b] 的随机整数,使用 (rand() % (b-a))+ a + 1;

4)示例代码

#include <iostream>
#include <ctime>
#include <cstdlib>
 
int getRand(int min, int max);
 
int main() {
 
    srand(time(0));
 
    for (int i=0; i<10; i++) {
        int r = getRand(2,20);
        std::cout << r << std::endl;
    }
 
    return 0;
}
 
// 左闭右闭区间
int getRand(int min, int max) {
    return ( rand() % (max - min + 1) ) + min ;
}

使用random库:c++11 random library
C++11之前,无论是C,还是C++都使用相同方式的来生成随机数,而在C++11中提供了随机数库,包括随机数引擎类、随机数分布类,简介如下:

随机数引擎类
一般使用 default_random_engine 类,产生随机非负数(不推荐直接使用)

直接使用时:

#include <iostream>
#include <ctime>
#include <random>
 
int main() {
 
    std::default_random_engine e;
    e.seed(time(0));
 
    for (int i=0; i<10; i++) {
        std::cout << e() << std::endl;
    }
 
    return 0;
}

输出结果:

16807
282475249
1622650073
984943658
1144108930
470211272
101027544
1457850878
1458777923
2007237709

随机数分布类
uniform_int_distribution:产生均匀分布的整数
示例代码:

#include <iostream>
#include <ctime>
#include <random>
 
int main() {
 
    std::default_random_engine e;
    std::uniform_int_distribution<int> u(2,20); // 左闭右闭区间
    e.seed(time(0));
 
    for (int i=0; i<10; i++) {
        std::cout << u(e) << std::endl;
    }
 
    return 0;
}

输出结果:

4
5
16
17
15
17
6
10
13
13

uniform_real_distribution:产生均匀分布的实数

#include <iostream>
#include <ctime>
#include <random>
 
int main() {
 
    std::default_random_engine e;
    std::uniform_real_distribution<double> u(1.5,19.5); // 左闭右闭区间
    e.seed(time(0));
 
    for (int i=0; i<10; i++) {
        std::cout << u(e) << std::endl;
    }
 
    return 0;
}

输出结果:

11.9673
2.29179
9.82668
9.82764
10.2394
13.8324
2.95336
9.72177
16.5145
12.1421

normal_distribution:产生正态分布的实数
示例代码:

#include <iostream>
#include <ctime>
#include <random>
 
int main() {
 
    std::default_random_engine e;
    std::normal_distribution<double> u(0,1); // 均值为0,标准差为1
    e.seed(time(0));
 
    for (int i=0; i<10; i++) {
        std::cout << u(e) << std::endl;
    }
 
    return 0;
}

输出结果:

0.390995
-0.680137
-1.02953
-0.53243
0.375886
-0.19804
-0.796159
0.837714
0.899632
2.06609

bernoulli_distribution:生成二项分布的布尔值

#include <iostream>
#include <ctime>
#include <random>
 
int main() {
 
    std::default_random_engine e;
    std::bernoulli_distribution u(0.8); // 生成1的概率为0.8
    e.seed(time(0));
 
    for (int i=0; i<10; i++) {
        std::cout << u(e) << std::endl;
    }
 
    return 0;
}

输出结果:

1
0
1
1
1
1
1
1
1
1

自己定义的一个随机产生数

#include <iostream>
#include <ctime>
#include <cstdlib>

int getRand(int min, int max);

int main() {

	srand(time(0));

	for (int i = 0; i < 10000; i++) {
		for (int j = 0; j < 30000; j++)//模拟定时器
		{
			for (int j = 0; j < 3000; j++)
			{
				
			}
		}
		int r = getRand(2, 20);
		std::cout << r << std::endl;
	}

	return 0;
}

// 左闭右闭区间
int getRand(int min, int max) {
	return (rand() % (max - min + 1)) + min;
}

三、错误集中

3.1queue是未声明标识

【问题】我使用了#include,可是打queuequeue语句时显示queue是未声明标识
我使用了#include,可是打queuequeue语句时显示queue是未声明标识符,queue字母也不是正常的蓝色是黑色。
【回答】加上using namespace std;

四、C++多线程加锁代码-Windows平台

#include <iostream>
#include <thread>
#include <string>
#include <mutex>//互斥锁
/*
1.Mutex 系列类(四种)(https://www.cnblogs.com/haippy/p/3237213.html)
	std::mutex,最基本的 Mutex 类。
	std::recursive_mutex,递归 Mutex 类。
	std::time_mutex,定时 Mutex 类。
	std::recursive_timed_mutex,定时递归 Mutex 类
2.volatile是一个特征修饰符(type specifier).volatile的作用是作为指令关键字,确保本条指令不会因编译器的优化而省略,
    且要求每次直接读值。
3.std::mutex 的成员函数
	构造函数,std::mutex不允许拷贝构造,也不允许 move 拷贝,最初产生的 mutex 对象是处于 unlocked 状态的。
	lock(),调用线程将锁住该互斥量。线程调用该函数会发生下面 3 种情况:
		(1). 如果该互斥量当前没有被锁住,则调用线程将该互斥量锁住,直到调用 unlock之前,该线程一直拥有该锁。
		(2). 如果当前互斥量被其他线程锁住,则当前的调用线程被阻塞住。
		(3). 如果当前互斥量被当前调用线程锁住,则会产生死锁(deadlock)。
	unlock(), 解锁,释放对互斥量的所有权。
	try_lock(),尝试锁住互斥量,如果互斥量被其他线程占有,则当前线程也不会被阻塞。线程调用该函数也会出现下面3 种情况,
		(1). 如果当前互斥量没有被其他线程占有,则该线程锁住互斥量,直到该线程调用 unlock 释放互斥量。
		(2). 如果当前互斥量被其他线程锁住,则当前调用线程返回 false,而并不会被阻塞掉。
		(3). 如果当前互斥量被当前调用线程锁住,则会产生死锁(deadlock)。
4.std是一个命名空间(namespace),‘::’是作用域运算符,cout是std空间中的一个函数名。使用cout时,必须有使用std命名空间的说明,有两种说明方式。
	方式一:每次使用时对cout说明:       
			std::cout << "Input two numbers:";
	方式二:在主函数前说明一下,后面就可以直接使用cout:
			using namespace std;
			cout << "Input two numbers:";
5.td::this_thread::yield: 当前线程放弃执行,操作系统调度另一线程继续执行。即当前线程将未使用完的“CPU时间片”让给其他线程使用,等其他线程使用完后再与其他线程一起竞争"CPU"。
  std::this_thread::sleep_for: 表示当前线程休眠一段时间,休眠期间不与其他线程竞争CPU,根据线程需求,等待若干时间。
6.
*/
// 车票总数是100张
volatile int tickets = 100;//
// 全局的互斥锁
std::mutex mtx;
 
// 线程函数
void sellTicketTask(std::string wndName)
{
	while (tickets > 0)
	{
		// 获取互斥锁资源
		mtx.lock();
		if (tickets > 0)
		{
			std::cout << wndName << " 售卖第" << tickets << "张票" << std::endl;
			tickets--;
		}
		// 释放互斥锁资源
		mtx.unlock();
 
		// 每卖出一张票,睡眠100ms,让每个窗口都有机会卖票
		std::this_thread::sleep_for(std::chrono::milliseconds(100));//std::this_thread::sleep_for表示当前线程休眠一段时间,休眠期间不与其他线程竞争CPU,根据线程需求,等待若干时间。
	}
}
 
// 模拟车站窗口卖票,使用C++11 线程互斥锁mutex
int main()
{
	// 创建三个模拟窗口卖票线程
	std::thread t1(sellTicketTask, "车票窗口一");
	std::thread t2(sellTicketTask, "车票窗口二");
	std::thread t3(sellTicketTask, "车票窗口三");
 
	// 等待三个线程执行完成
	t1.join();
	t2.join();
	t3.join();
 
	return 0;
}
#include <windows.h>
#include <iostream>
#include <thread>
#include <mutex>
#include <string>
 
using namespace std;//使用标准命名空间:(https://baike.baidu.com/item/using%20namespace%20std/10360651?fr=aladdin)
 
//DWORD WINAPI Fun1(LPVOID lpParameter);//LPVOID这个是一个宏定义 表示的是指向空类型的指针
 
//DWORD WINAPI Fun2(LPVOID lpParameter);
//DWORD WINAPI Fun3(LPVOID lpParameter);
 
// 全局的互斥锁
std::mutex mtx;
 
int index = 0;
//int money = 100;
int tickets = 100;   //全局变量tickets用来表示销售的剩余票数
					 //线程1入口函数
					 //DWORD WINAPI Fun1(LPVOID lpParameter)
int Fun1(std::string wndName)
{
 
	while (TRUE)
	{
		mtx.lock();
		if (tickets > 0)
		{
			cout << "车票窗口一 : " << tickets-- << endl;//表示输出换行的意思,相当于C语言里面的printf("\n");
 
		}
		else
		{
			break;
		}
		mtx.unlock();
		Sleep(1);
 
	}
	return 0;
}
 
//线程2的入口函数
//DWORD WINAPI Fun2(std::string wndName)
int Fun2(std::string wndName)
{
	while (TRUE)
	{
		mtx.lock();
		if (tickets > 0)
		{
			
			cout << "车票窗口二 : " << tickets-- << endl;
		}
		else
		{
			break;
		}
		mtx.unlock();
		Sleep(1);
	}
	return 0;
}
//DWORD WINAPI Fun3(std::string wndName)
int Fun3(std::string wndName)
{
	while (TRUE)
	{
		mtx.lock();
		if (tickets > 0)
		{
			
			cout << "车票窗口三: " << tickets-- << endl;
		}
		else
		{
			break;
		}
		mtx.unlock();
		Sleep(1);
	}
	return 0;
}
 
///
int main(int argc, TCHAR* argv[])
{
	/*HANDLE hThread1;//Handler:是一个消息分发对象,进行发送和处理消息
	HANDLE hThread2;//Handler:无类型指针(不指向任何类型数据的指针)
	HANDLE hThread3;
					//创建线程
	hThread1 = CreateThread(NULL,//有没有安全性描述
		0,	//默认线程栈的大小(让新线程采用与调用线程一样的栈大小)
		Fun1, //指定线程的入口函数地址(线程函数指针)
		NULL,//这里就是你要传进Fun1函数的参数
		0,// 没有附加属性
		NULL);// 不需要获得线程id,线程创建标记,0表示让线程一旦创立就运行、新线程的ID,不需要的话为null
	hThread2 = CreateThread(NULL, 0, Fun2, NULL, 0, NULL);
	hThread3 = CreateThread(NULL, 0, Fun3, NULL, 0, NULL);
	CloseHandle(hThread1);  //调用CloseHandle将此线程的句柄关闭,关闭句柄时,系统会递减该线程内核对象的使用计数。
	CloseHandle(hThread2);
	CloseHandle(hThread3);
	Sleep(4000); //让线程暂停运行4s
	system("pause");
	return 0;
	*/
 
	std::thread t1(Fun1, "车票窗口一");
	std::thread t2(Fun2, "车票窗口二");
	std::thread t3(Fun3, "车票窗口三");
 
	t1.join();
	t2.join();
	t3.join();
 
	return 0;
 
}
 

五、【C/C++】Sleep函数的用法

Sleep函数

功能: 执行挂起一段时间,也就是等待一段时间在继续执行

用法:Sleep(时间)

头文件:Windows下为–> windows.h

 Linux 下为 --> unistd.h

注意:(1)Sleep是区分大小写的,有的编译器是大写,有的是小写。

(2)Sleep括号里的时间,在windows下是已毫秒为单位,而Linux是以秒为单位

#include<stdio.h>
#include<stdlib.h>
#include<windows.h>
int main()
{	
	int a = 1;
	while (a)
	{
		printf("Welcome to songjiahao's blog\n");
		Sleep(1000);
	}
	system("pause");
	return 0;
}

点赞(0) 打赏

评论列表 共有 0 条评论

暂无评论

微信公众账号

微信扫一扫加关注

发表
评论
返回
顶部