网络通讯学习(1)---TCP通讯

2023-05-16

TCP/IP四层模型

在这里插入图片描述
在这里插入图片描述

UDP/TCP协议

TCP(The Transmission Control Protocol):传输控制协议

UDP/TCP协议都属于传输层协议,都位于IP协议以上,将UDP/TCP数据报封装于IP数据内传输。

UDP首部:包含源端口,目标端口等数据。端口保证数据能准确传输到指定的进程。

IP协议是不可靠协议,UDP本身没有任何确保可靠的措施,故UDP协议也是不可靠协议。UDP协议适用于对数据可靠性,顺序交付无要求的程序,UDP能提供更快,更小消耗的传输服务。

TCP首部:相比UDP,TCP同样包含源端口,目标端口等数据的同时,TCP还包含序号,确认号等信息,这些数据用于确认数据是否被完整交付,TCP是可靠协议的原因就在这里。

TCP虽然建立在不可靠协议IP之上,但TCP采用了多种机制,确保数据有序,可靠的交付。TCP多用于对数据安全要求较高的应用,如Web,电子邮件等。

Socket编程

套接字的概念

套接字,是操作系统内核中的一个数据结构。它是网络中的节点进行相互通信的门户。它是网络进程的ID。

网络通信,归根究竟还是进程间的通信(不同计算机上的进程间通信)。在网络中。每个节点(计算机或路由)都有一个网络地址。也就是IP地址。

两个进程通信时,首先要确定各自所在的网络节点的网络地址。可是,网络地址仅仅能确定进程所在的计算机,而一台计算机上非常可能同一时候执行着多个进程,所以仅凭网络地址还不能确定究竟是和网络中的哪一个进程进行通信。因此套接口中还须要包含其它的信息。也就是port号(PORT)。在一台计算机中,一个port号一次仅仅能分配给一个进程,也就是说,在一台计算机中,port号和进程之间是一一相应关系。

所以,使用port号和网络地址的组合能够唯一的确定整个网络中的一个网络进程。

在这里插入图片描述

​ 网络编程也称为socket编程,socket通常译作”套接字“,为一套网络编程的接口API,但原意其实意译应该为”接口“。也就是操作系统提供给开发人员进行网络开发的API接口。这套接口通常可以通过参数的调整支持多种协议,包括TCP、UDP和IP等等。

​ 从编码角度看,源IP地址和目的IP地址以及源端口号和目的端口号的组合称为套接字。其用于标识客户端请求的服务器和服务。

在这里插入图片描述

流套接字(SOCK_STREAM)------>使用TCP协议,能够实现可靠的数据服务,提供面向连接、可靠的数据传输服务。该服务将保证数据能够实现无差错、无重复发送,并按顺序接收。

数据报套接字(SOCK_DGRAM)------>使用UDP协议,提供无连接的服务,无法保证数据传输的可靠性,数据有可能在传输过程中丢失或出现数据重复,且无法保证顺序地接收到数据。

原始套接字(SOCK_RAW)------>允许对较低层次的协议直接访问,比如IP、 ICMP协议,它常用于检验新的协议实现,或者访问现有服务中配置的新设备,能够对网络底层的传输机制进行控制,所以可以应用原始套接字来操纵网络层和传输层应用。比如,我们可以通过RAW SOCKET来接收发向本机的ICMP、IGMP协议包,或者接收TCP/IP栈不能够处理的IP包,也可以用来发送一些自定包头或自定协议的IP包。网络监听技术很大程度上依赖于SOCKET_RAW。

应用编程接口即:调用一些操作系统提供的api,来与应用进程进行交互。而socket api是一套与网络通讯相关的、操作系统提供给应用开发的编程接口,如:微软公司在其操作系统中采用了套接字接口 API ,形成了一个稍有不同的 API,并称之为Windows Socket Interface或WINSOCK。

  • WSAStartup函数:
    在这里插入图片描述

使用Socket的应用程序在使用Socket之前必须首先调用 WSAStartup函数,两个参数:

第一个参数指明程序请求使用的WinSock版本,其中高位字节指明副版本、低位字节指明主版本.十六进制整数,例如0x102表示2.1版。

第二个参数指向WSADATA结构的指针

返回实际的WinSock的版本信息。

  • WSACleanup函数:int WSACleanup(void);

​ 应用程序在完成对请求的Socket库的使用,最后要调用WSACleanup函数解除与Socket库的绑定并释放Socket库所占用的系统资源 。不清理的话,在运行codeblocks的时候,常常可能会发生id.exe被占用错误。无法运行,需要去管理器找进程关掉才可以继续运行。

  • socket函数:sd = socket(protofamily,type,proto);

    创建套接字,操作系统返回套接字描述符(sd)

    第一个参数(协议族): protofamily = PF_INET(TCP/IP)

    第二个参数(套接字类型): type = SOCK_STREAM,SOCK_DGRAM or SOCK_RAW(TCP/IP)

    第三个参数(协议号):0为默认

TCP通讯实例

在这里插入图片描述

1、首先,Winsock API 函数由WS2_32.DLL支持,可通过WS2_32.LIB访问。故Windows socket编程前需要加载ws2_32.lib,然后初始化WS2_32.DLL,通过函数WSAStartup完成初始化。一般程序最后需要终止DLL使用,此时需要调用WSACleanup函数。

ws2_32.dll是Windows Sockets应用程序接口, 用于支持Internet和网络应用程序。

DLL 是一个库,其中包含可同时由多个程序使用的代码和数据。对于Windows,操作系统的很多功能都由 DLL 提供。

//以下是加载库,以及初始化
#include<stdio.h>
#include<WinSock2.h>
#pragma comment (lib,"ws2_32.lib");			//加载ws2_32.lib

int main()
{
    //1、ws2_32.DLL初始化
	WSADATA wsaData;
	/*
	* socket编程中:
		声明调用不同的Winsock版本。
		例如MAKEWORD(2,2)就是调用2.2版,MAKEWORD(1,1)就是调用1.1版。
	*/
	WSAStartup(MAKEWORD(2,2),&wsaData); //初始化
    /*
    *中间代码
    */
    
    WSACleanup();   //终止DLL使用
}

2、随后,创建socket套接字。

	//2、创建套接字
	/*
	*	typedef    UINT_PTR        SOCKET;
	*	typedef    unsigned int    UINT_PTR;
	*	在32位操作系统里,一个unsigned int是4个字节。64位操作系统上,一个unsigned int是8个字节。所以用UINT_PTR代替int理论上可以让代码具有更好的移植性,当然也让代码看起来更专业.
	* socket(int domain, int type, int protocol);
	* int domain参数表示套接字要使用的协议簇,网络编程一般使用AF_INET宏,AF_INET(TCP/IP – IPv4)
	* type参数指的是套接字类型,SOCK_STREAM(TCP流),SOCK_DGRAM(UDP数据报)
	* protocol表示协议,使用AF_INET簇,TCP连接时,设为IPPROTO_TCP。
	*/
	SOCKET serverSock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

3、创建套接字之后,绑定套接字.

​ Socket套接字基于计算机网络,提供同一系统上不同进程或由局域网连接在一起的不同机器上的进程间通讯功能。如下图:

在这里插入图片描述

​ 套接字通过IP地址、Port端口号标识,通过这个标识可以在整个局域网定位一个套接字,通过套接字进程便可以相互传输数据。而这就是绑定套接字所做的工作,即为每一个套接字绑定相应的IP地址和端口号标识。

	//3、绑定套接字
	/*
	* struct sockaddr_in这个结构体用来处理网络通信的地址。
	  在各种系统调用或者函数中,只要和网络地址打交道,就得用到这两个结构体。网络       中的地址包含3个方面的属性:
	  1 地址类型; 2 ip地址; 3 端口
	*/
	SOCKADDR_IN sockAddr;
	/*
	* memset 函数是内存赋值函数,用来给某一块内存空间进行赋值的。(对一片内存空间逐字节进行初始化) 
	* 其原型是:void* memset(void *_Dst, int  _Val, size_t _Size)
    * _Dst是目标起始地址,_Val是要赋的值,_Size是要赋值的字节数
	*/
	memset(&sockAddr,0,sizeof(sockAddr));  //初始化

	sockAddr.sin_family = AF_INET;   //地址类型
	sockAddr.sin_addr.s_addr = inet_addr("127.0.0.1");     //IP地址(127.0.0.1是回送地址,指本机)
	sockAddr.sin_port = htons(9080);    //端口号  htons函数:将主机字节顺序转化为网络字节顺序

	bind(serverSock,(SOCKADDR*)&sockAddr,sizeof(SOCKADDR));

​ 关于SOCKADDR_IN和SOCKADDR在另外文档中有详解。

bind函数将socket与协议、IP和端口号绑定起来,相对于给socket“命名”唯一的标识,这样其他的进程就可以通过这个标识找到这个socket。

//关于bind函数
int bind(int sockfd, const struct sockaddr *addr,socklen_t addrlen);
//函数作用:将本地地址与套接字关联起来。
//函数参数:
//   (1)参数 sockfd ,需要绑定的socket。
//  (2)参数 addr ,存放了服务端用于通信的地址和端口。
//  (3)参数 addrlen ,表示 addr 结构体的大小
//返回值:成功则返回0 ,失败返回-1,错误原因存于 errno 中。如果绑定的地址错误,或者端口已被占用,bind 函数一定会报错,否则一般不会返回错误。

//关于inet_addr函数
unsigned long WSAAPI inet_addr(const char *cp);
//功能:inet_addr函数将包含 IPv4 点分十进制地址的字符串转换为 IN_ADDR 结构的 正确 地址
//参数:cp代表点分十进制的IP地址,如1.2.3.4
//返回值:
/*如果没有发生错误,inet_addr函数将返回一个无符号长整型值,其中包含给定 Internet 地址的合适二进制表示。
  如果cp参数中的字符串不包含合法的 Internet 地址,例如,如果“abcd”地址的一部分超过 255,则 inet_addr返回值INADDR_NONE。
*/

4、进入监听状态

//4、进入监听状态
	listen(serverSock,20);

int listen(SOCKET s, int nQueueSize);

第一个参数: 监听的socket。

第二个参数: 套接字监听队列最大连接请求数。

该函数将监听对socket的连接请求

5、

	//5、定义接受客户端请求的数据结构变量
	SOCKADDR cltAddr;
	int nSize = sizeof(cltAddr);
	//buffer是一块共用的内存,刚开始接收的数据放在这里面,给客户端回复消息也用的这块内存
	char buffer[BUF_SIZE] = { 0 };
	while (1)
	{
		//6、阻塞直到客户端发来消息,创建客户socket
		SOCKET clientSock = accept(serverSock,(SOCKADDR*)&cltAddr,&nSize);

		//7、接受客户端数据
		int strLen = recv(clientSock, buffer, BUF_SIZE, 0);  //数据存放在buffer这个字符串数组中
		printf("Message form client: %s\n", buffer);

		//8、给客户端回复消息
		printf("Input a string:\n");
		getss(buffer,BUF_SIZE);
		send(clientSock, buffer, strLen, 0);

		//9、关闭客户端套接字
		closesocket(clientSock);

		//10、重置缓冲区
		memset(buffer,0,BUF_SIZE);

	}
  • 接受连接请求

SOCKET accept(SOCKET s, struct sockaddr *addr, int *addrlen);

第一个参数: socket为被监听的socket,即服务端socket

第二个参数: 对应AF_INET,一个sockaddr指针,将写入发送请求方的sockaddr_in信息,即客户端的sockaddr_in信息。

第三个参数: 对应AF_INET,sockaddr结构体的大小。

该函数用于接受一个socket连接请求,返回一个新的连接socket(可以理解为客户端的socket),发送与接收数据通过这个连接socket。

  • 发送数据

int send(SOCKET s, const char *buf, int len, int flags );

第一个参数: socket为对方的socket。

第二个参数: 发送数据的缓冲区。

第三个参数: 数据缓冲区大小。

第四个参数: 紧急状态,一般值为0。

该函数用于向对方socket发送数据,成功返回发送数据的大小数

  • 接受数据

int recv(SOCKET s, char *buf, int len, int flags);

第一个参数: socket为对方的socket。

第二个参数: 接收数据的缓冲区。

第三个参数: 缓冲区大小。

第四个参数: 紧急状态,一般为0。

该函数用于接收对方发送的数据,成功返回发送数据的大小数

最后关闭服务端套接字、终止DLL使用即可

服务器端的源码:

#include<stdio.h>
#include<WinSock2.h>
#pragma comment (lib,"ws2_32.lib");			//加载ws2_32.lib
#pragma warning (disable:4996);			//解决C4996 'inet_addr'错误
#define BUF_SIZE 100

/*
* char* getss(char* str, int num)
{
	if (fgets(str, num, stdin) != 0)
	{
		//size_t是标准C库中定义的,在64位系统中为long long unsigned int
		size_t len = strlen(str);
		if (len > 0 && str[len - 1] == 'n')
			str[len - 1] = ' ';
		return str;
	}
}
*/

int main()
{
	//1、ws2_32.DLL初始化
	WSADATA wsaData;
	/*
	* socket编程中:
		声明调用不同的Winsock版本。
		例如MAKEWORD(2,2)就是调用2.2版,MAKEWORD(1,1)就是调用1.1版。
	*/
	WSAStartup(MAKEWORD(2,2),&wsaData); //初始化


	//2、创建套接字
	/*
	*socket(int domain, int type, int protocol);
	* 其中 “int domain”参数表示套接字要使用的协议簇  AF_INET(TCP/IP – IPv4)
	* “type”参数指的是套接字类型,SOCK_STREAM(TCP流),SOCK_DGRAM(UDP数据报)
	* protocol”一般设置为“0
	*/
	SOCKET serverSock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

	//3、绑定套接字
	/*
	* struct sockaddr_in这个结构体用来处理网络通信的地址。
		在各种系统调用或者函数中,只要和网络地址打交道,就得用到这两个结构体。网络中的地址包含3个方面的属性:
		1 地址类型; 2 ip地址; 3 端口
	*/
	SOCKADDR_IN sockAddr;
	/*
	* memset 函数是内存赋值函数,用来给某一块内存空间进行赋值的。(对一片内存空间逐字节进行初始化) 
	* 其原型是:void* memset(void *_Dst, int  _Val, size_t _Size)
    * _Dst是目标起始地址,_Val是要赋的值,_Size是要赋值的字节数
	*/
	memset(&sockAddr,0,sizeof(sockAddr));  //初始化

	sockAddr.sin_family = AF_INET;   //地址类型
	sockAddr.sin_addr.s_addr = inet_addr("127.0.0.1");     //IP地址(127.0.0.1是回送地址,指本机)
	sockAddr.sin_port = htons(9080);    //端口号  htons函数:将主机字节顺序转化为网络字节顺序

	bind(serverSock,(SOCKADDR*)&sockAddr,sizeof(SOCKADDR));

	//4、进入监听状态
	listen(serverSock,20);
	printf("服务器进入监听状态...\n");

	//5、定义接受客户端请求的数据结构变量
	SOCKADDR cltAddr;
	int nSize = sizeof(cltAddr);
	char buffer[BUF_SIZE] = { 0 };
	int num = 0;
	while (1)
	{
		//6、阻塞直到客户端发来消息,创建客户socket
		SOCKET clientSock = accept(serverSock,(SOCKADDR*)&cltAddr,&nSize);
		if(!num)
			printf("连接成功\n");	

		//7、接受客户端数据
		int strLen = recv(clientSock, buffer, BUF_SIZE, 0);
		printf("Message form client: %s\n", buffer);

		//8、给客户端回复消息
		printf("Input a string to client:");
	//	getss(buffer, sizeof(buffer));
		gets(buffer);
		send(clientSock, buffer, strLen, 0);

		//9、关闭客户端套接字
		closesocket(clientSock);

		//10、重置缓冲区
		memset(buffer,0,BUF_SIZE);
		num++;
	}

		//11、关闭服务端套接字
		closesocket(serverSock);

		//12、终止DLL使用
		WSACleanup();
}

注:目前GCC中还没有完全实现此标准, 因此 gets_s() 函数尚未包含在目前的GNU 工具链中,因此调用gets_s函数出错,这里干脆写了一个getss函数。

这是老师写的getss函数,我感觉直接用gets函数都可以。

关于fgets函数:

char *fgets(char *buf, int bufsize, FILE *stream);
参数
*buf: 字符型指针,指向用来存储所得数据的地址。
bufsize: 整型数据,指明存储数据的大小。
*stream: 文件结构体指针,将要读取的文件流。
返回值

成功,则返回第一个参数buf;

在读字符时遇到end-of-file,则eof指示器被设置,如果还没读入任何字符就遇到这种情况,则buf保持原来的内容,返回NULL;
如果发生读入错误,error指示器被设置,返回NULL,buf的值可能被改变。

客户端跟服务端类似,源码如下:

#include<stdio.h>
#include<Winsock2.h>
#pragma comment(lib,"ws2_32.lib")
#pragma warning(disable:4996)

#define BUF_SIZE 100

/*
char* getss(char* str, int num)
{
	if (fgets(str, num, stdin) != 0)
	{
		size_t len = strlen(str);
	//	if (len > 0 && str[len - 1] == 'n')
	//		str[len - 1] = ' ';
		return str;
	}
	return 0;
}
*/

int main()
{
	//初始化DLL
	WSADATA wsaData;
	WSAStartup(MAKEWORD(2, 2), &wsaData);

	//创建套接字
	SOCKADDR_IN sockAddr;
	memset(&sockAddr, 0, sizeof(sockAddr));
	sockAddr.sin_family = AF_INET;
	sockAddr.sin_addr.s_addr = inet_addr("127.0.0.1");
	sockAddr.sin_port = htons(9080);

	char bufSend[BUF_SIZE] = { 0 };
	char bufRecv[BUF_SIZE] = { 0 };

	while (1)
	{
		// 3、创建客户端套接字
		SOCKET sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

		// 4、连接服务器
		connect(sock, (SOCKADDR*)&sockAddr, sizeof(SOCKADDR));

		//5、获取用户输入的字符串发送给服务器
		printf("Input a string:");
		gets(bufSend);
	//	getss(bufSend, sizeof(bufSend));
		send(sock, bufSend, BUF_SIZE, 0);

		//6、接受服务器传回来的消息
		recv(sock, bufRecv, BUF_SIZE, 0);
		printf("Message form server: %s\n",bufRecv);

		//7、重置缓冲区
		memset(bufSend, 0, BUF_SIZE);
		memset(bufRecv, 0, BUF_SIZE);

		// 8、关闭套接字
		closesocket(sock);				
	}
	// 9、终止DLL使用
	WSACleanup();
	return 0;
}

注意connect函数即可:

int connect(SOCKET s,const struct sockaddr *saddr,int namelen) ;

第一个参数: socket本地进程的socket。

第二个参数: 对应AF_INET,对方IP,端口等socket地址标识sockaddr_in。

第三个参数: 对应AF_INET,使用sockaddr_in结构大小。

补充知识

什么是pragma

#pragma指令的作用是:用于指定计算机或操作系统特定的编译器功能。C 和 C++ 的每个实现均支持某些对其主机或操作系统唯一的功能。

  • #pragma once

大家应该都知道:指定该文件在编译源代码文件时仅由编译器包含(打开)一次
使用 #pragma once 可减少生成次数,和使用预处理宏定义来避免多次包含文件的内容的效果是一样的,但是需要键入的代码少,可减少错误率。

  • #pragma waring(…)

    启用编译器警告消息的行为和选择性修改。

    #pragma warning( disable : 4507 34; once : 4385; error : 164 ) //这1行跟下面3行效果一样

    #pragma warning( disable : 4507 34 ) //不发出4507和34警告,即有4507和34警告时不显示
    #pragma warning( once : 4385 ) //4385警告信息只报告一次
    #pragma warning( error : 164 ) //把164警告信息作为一个错误

  • #pragma comment(comment-type [,“commentstring”])

    该指令将一个注释记录放入一个对象文件或可执行文件中。

    comment-type 是一个预定义的标识符(如下所述,一共5个),它指定了注释记录的类型。 可选 commentstring 是一个字符串,它提供了某些注释类型的附加信息。 由于 commentstring 是一个字符串,因此它遵循有关转义字符、嵌入的引号 (") 和串联的字符串的所有规则。

    • compiler
      将编译器的名称和版本号置于对象文件中。 此注释记录将被链接器忽略。 如果为此记录类型提供 commentstring 参数,则编译器会生成警告。

    • exestr
      将 commentstring 置于对象文件中。 在链接时,会将该字符串置于可执行文件内。 加载可执行文件时,不会将字符串加载到内存中;但是,可以使用在文件中查找可打印字符串的程序来找到它。 此注释记录类型的一个用途是将版本号或类似信息嵌入可执行文件中。

    • linker
      将链接器选项置于对象文件中。 可以使用注释类型来指定链接器选项,而不是将其传递到命令行或在开发环境中指定它。

    • user
      将一般注释置于对象文件中。 commentstring 参数包含注释文本。 此注释记录将被链接器忽略。

    • lib(这个最常用了)
      将库搜索记录置于对象文件中。 此注释类型必须带有包含您希望链接器搜索的库的名称(和可能的路径)的 commentstring 参数。 库名称遵循对象文件中的默认库搜索记录;链接器会搜索此库,这就像在命令行上对其命名一样,前提是未使用 /nodefaultlib 指定库。 可以将多个库搜索记录置于同一个源文件中;各个记录将以其在源文件中显示的顺序出现在对象文件中。

      如果默认库和添加的库的顺序很重要,则使用 /Zl 开关进行编译会阻止将默认库名称置于对象模块中。 然后,可使用另一个注释指令在添加的库的后面插入默认库的名称。 与这些指令一起列出的库将以其在源代码中的发现顺序出现在对象模块中。

  • #pragma message(messageString)

    不中断编译的情况下,发送一个字符串文字量到标准输出。message编译指示的典型运用是在编译时显示信息。

MAKEWORD解释

​ MAKEWORD是将两个byte型合并成一个word型,一个在高8位(b),一个在低8位(a)

​ 比如a=2;b=1
​ 2的二进制是00000010,1的二进制为00000001,B是表示高8位,A表示低8位 合并起来就是100000010

Connect函数

int WSAAPI connect(

SOCKET s,

const struct sockaddr FAR * name,

int namelen

);

s

标识未连接套接字的描述符。

name

指向应建立连接的sockaddr结构的指针。

namelen

name参数指向的sockaddr结构的长度(以字节为单位)。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

网络通讯学习(1)---TCP通讯 的相关文章

  • string、char*和char[]的转换

    char 和const char 的转换 const char 转 char xff08 1 xff09 为什么不能直接赋值 xff1f 这里你可以这么想 xff0c 假如const char类型字符串可以赋值给char类型 xff0c 那
  • 11-串口通信

    微控制器与外部设备的数据通信 xff0c 分为并行通信和串行通信 并行 xff1a 数据的各位同时发送或接受 xff0c 每个数据位使用一条导线 串行 xff1a 数据一位接一位地顺序发送或接收 串行通信有SPI IIC UART多种 xf
  • C语言编程规范设置 (vscode设置)

    1 打开vscode设置后 2 搜索format 3 把以下选项打上对勾 Editor Format On Paste Editor Format On Save Editor Format On Type 4 C Cpp 这一选项选择以下
  • c++ vscode 环境一键配置

    致谢 首先感谢原作者为我等初学者所做的软件 xff0c 其他文章讲了一堆的东西都没解决 xff0c 作者一个软件一步到位 xff0c 如果觉得不错的话可以star一下 xff0c 原作者视频地址 xff1a https www bilibi
  • 使用ESP8266实现单片机与上位机之间的wifi通信。

    使用ESP8266实现单片机与上位机之间的wifi通信 首先弄清楚8266的工作模式 xff0c 分别是 模式1 xff1a station xff0c 模式2 xff1a ap xff0c 模式3 xff1a station 43 ap
  • 【C 陷阱与缺陷】(四)连接

    码字不易 xff0c 对你有帮助 点赞 转发 关注 支持一下作者 微信搜公众号 xff1a 不会编程的程序圆 看更多干货 xff0c 获取第一时间更新 代码 xff0c 练习上传至 xff1a https github com hairrr
  • DIY无人机(匿名拓控者P2+F330机架)

    今年三月份的时候DIY过一个大疆NAZA 43 F450机架的无人机 xff0c 第一次体验DIY多旋翼无人机的全流程 xff0c 目的其实是为了后面更深入了解做准备 不然的话 xff0c 这钱买个大疆MINI3不香吗 xff1f DIY无
  • 在lammps模拟过程中的常用势函数设置

    文章目录 1 lj cut1 1 lj cut在in文件中使用方法1 2 lj cut在data文件中使用方法1 3 lj cut参数查询方法1 4 lj cut参数单位转换方法1 5 lj cut不同原子之间的参数1 6 lj cut参数
  • C语言十进制转16进制

    int DEC HEX uint32 t Dec int ram 61 0 整 int ray 61 0 余 uint32 t Hex 61 0x0 int i 61 0 do ram 61 Dec 16 ray 61 Dec 16 Dec
  • Windows系统下的Visual studio2019 安装 opencv4.5.1的安装

    OpenCV文档 xff1a https docs opencv org 4 5 1 examples html 安装OpenCV 4 5 1 xff0c 下载地址 https opencv org releases 下载完成后得到open
  • STM32串口初始化与使用详解(基于HAL库编程)

    STM32串口初始化与使用详解 串口简介串口初始化具体步骤串口收发理论代码执行 串口简介 USART Universal Synchronous Asynchronous Receiver Transmitter 通用同步 异步串行接收发送
  • STM32F103C8T6+OV7670(有FIFO和无FIFO版本)入门教程/使用总结(待续写,有问题可发在评论区中)

    前言 xff1a 本文为第一遍草稿 xff0c 错误会有点多 xff08 指技术性的东西会叫错等等 xff0c 欢迎纠正 xff09 xff0c 有需要可以先看看 OV7670还没有完全弄清楚 xff0c 目前已成功出图 xff08 指测试
  • 串口DMA实现接收--不定长度接收

    1 DMA接收配置 1 direction xff1a 数据传输的方向是外设 xff08 串口 xff09 gt 内存 xff08 DMA Buff xff09 xff1b 2 memory inc xff1a 内存自增 xff0c 内存指
  • ROS信息的收发

    图像信息的收发 图像信息发送 include lt ros ros h gt include lt image transport image transport h gt 用于image的订阅和发布 xff0c 并为压缩模式compres
  • 标定工具Kalibr安装、使用及标定结果评估方法

    单目相机标定 安装和配置 cd kalibr workspace source devel setup bash 如果使用april tag标定板 xff0c 设置aprilgrid yaml配置文件 标定数据bag采集 采集单目标定数据时
  • 2.什么是机械设计?

    机械设计是研究如何创造机械 以使其安全 可靠地工作等的内容 机械的定义是 一个组装的零件系统 可以以预定和受控的方式传递运动和能量 或更简单地说 一个控制力和运动的系统 那么 设计是又是什么呢 设计 设 计 设就是设想 从无到有的想象 想象
  • 手把手教你实现一个单链表

    目录 一 节点声明二 尾插三 链表打印四 头插五 尾删六 头删七 查找值八 指定插入九 指定删除十 销毁链表 一 节点声明 链表是一种数据结构 xff0c 用于数据的存储 如图 xff0c 每一个链表节点所在的内存空间是不延续的 xff0c
  • 使用多线程以及RandomAccessfile来实现多线程复制文件

    Class RandomAccessFile 介绍 该类的实例支持读取和写入随机访问文件 随机访问文件的行为类似于存储在文件系统中的大量字节 有一种游标 xff0c 或索引到隐含的数组 xff0c 称为文件指针 输入操作读取从文件指针开始的
  • 线程池中线程抛了异常如何处理?

    文章目录 1 模拟线程池抛异常2 如何获取和处理异常方案一 xff1a 使用 try catch方案二 xff1a 使用Thread setDefaultUncaughtExceptionHandler方法捕获异常方案三 xff1a 重写a
  • ROS放弃指南2:ROS创建工作空间及五种设置环境变量的方法

    参考链接 xff1a 中国大学MOOC中的机器人操作系统入门 https www icourse163 org course ISCAS 1002580008 古月居博客 www guyuehome com 运行环境 xff1a Ubunt

随机推荐

  • 百科不全书之ROS函数解析

    1 ROS的回调函数 span class token comment 单线程 span ros span class token operator span span class token operator span span clas
  • VsCode 运行后终端没有结果

    最近入手了VsCode很多都还不太清楚 xff0c 稍微记录一下碰到的一点问题 也是第一次写博客 VsCode 运行后终端没有结果 一 运行后终端没有结果二 终端中文乱码问题 一 运行后终端没有结果 在网上试了好多好多解决方法都没有用 xf
  • STM32CubeMX(05) 移植陀螺仪MPU6050的DMP库读取三轴角度,加速度

    文章目录 前言一 MPU6050是什么 xff1f 二 STM32CubeMX配置2 1 IIC配置2 2 开启中断2 3 硬件连接2 4 软件编写 三 导入DMP库3 1 keil配置3 2 添加头文件路径3 3 添加头文件3 4 添加初
  • 基于STM32的智能GPS定位系统(云平台、小程序)

    如需源码或成品可以私我 背景及目标 前阵子 xff0c 准确的说是好几个月前买了一辆电瓶车 xff0c 当时呢因为车停得很随意 xff0c 所以想给小电驴装一个GPS xff0c 一方面是防盗 xff0c 另一方面是为了测速和绘制骑行轨迹
  • 蓝桥杯大赛

    第十一届蓝桥杯单片机比赛心得 前期的准备十月份省赛十一月份国赛错过结果发布 想要做一点事情 xff0c 传承 前期的准备 本次蓝桥杯大赛由于疫情原因延迟了将近7个月举行 xff0c 原先是3月份举行 xff0c 拖到了10月份 xff0c
  • 蓝桥杯模块练习之关闭外设

    蓝桥杯单片机比赛系列1初探关闭外设 关闭LED关闭继电器和蜂鸣器 关闭LED 本节将会介绍板子上的最简单最基础的部分 比赛一般上来需要关闭无关外设 xff0c 蓝桥杯的板子比较特殊 xff0c 51上电默认P0 O1 P2 P3都是高电平
  • 蓝桥杯模块练习之温度传感器DS18B20

    蓝桥杯单片机比赛系列4温度传感器DS18B20 温度传感器DS18B20原理相关电路onewire总线几个需要知道的暂存器和命令 代码解释修改代码自写代码 实现代码 温度传感器DS18B20原理 相关电路 DS18B20遵循onewire总
  • 被锡膏坑了一把

    锡膏 61 锡珠 43 助焊剂 把锡膏放大来看如下图 我是去年买的一罐锡膏 xff0c 138度的 xff0c 用了一两次 xff0c 然后就放在哪里没动它 xff0c 盖子也盖好了 xff0c 没有放冰箱 今年又拿出来用 xff0c 用钢
  • 蓝桥杯模块练习之AD/DA

    蓝桥杯单片机比赛系列6AD DA转换 AD DA原理相关电路pcf8591器件地址 代码解释修改代码AD自写代码ADDA AD DA原理 相关电路 通过pcf8591芯片实现ad转换 板子上ad采集主要采集滑动变阻器的电压值和与光敏电阻串联
  • 蓝桥杯模块练习之EEPROM

    蓝桥杯单片机比赛系列7EEPROM EEPROM原理相关电路AT24C02器件地址 EEPROM自写代码 EEPROM原理 相关电路 有了系列6的基础 xff0c 上手eeprom就简单多了 xff0c 板子上对应的器件是AT24C02 A
  • Openmv学习day1——色块识别

    find blobs函数 image find blobs thresholds roi 61 Auto x stride 61 2 y stride 61 1 invert 61 False area threshold 61 10 pi
  • 蓝桥杯嵌入式模块练习之扩展版MEME

    三轴传感器 PA4 7都不能作为其他用处 xff0c 三周传感器需要使用到这四个引脚资源 当然 xff0c 如果不用中断 xff0c 也可以只结PA4 5 xff0c PA6 7可接到温度传感器和温湿度传感器 这个外设的通信协议也是I2C跟
  • Github Pages 搭建网站

    个人站点 访问 https 用户名 gitub io 搭建步骤 1 创建个人站点 gt 新建仓库 xff08 仓库名必须是 用户名 github io xff09 2 在仓库下新建index heml文件即可 3 Github pages仅
  • 普通io口模拟串口通信

    之前公司在做项目的时候需要用到多串口 xff0c 板载串口资源不足 xff0c 就在网上找相关内容 xff0c 结合自己的理解做出虚拟串口 模拟串口需要用到两个普通io引脚 xff0c 一个定时器 软件串口的实现 IO模拟串口 波特率 xf
  • UART,SPI,IIC,RS232通信时序和规则

    一 UART 1 串口通信方式 2 串口通信步骤 注意 xff1a 串口协议规定 xff0c 闲置时必须是高电平 校验位 xff1a 是使用奇偶校验 停止位必须高电平 一个0和多个0区分是靠掐时间 异步通信 xff1a 时钟各不一样 二 I
  • kvaser pcie can 在ros中使用socketcan开发

    kvaser pcie can 在ros中使用socketcan开发 0 系统配置 Ubuntu 16 04 6 LTS Linux version 4 15 0 45 generic 1 官网下载地址 https www kvaser c
  • 算法训练 - 连接字符串 编程将两个字符串连接起来。例如country与side相连接成为countryside。   输入两行,每行一个字符串(只包含小写字母,长度不超过100);输出一行一个字符

    问题描述 编程将两个字符串连接起来 例如country与side相连接成为countryside 输入两行 xff0c 每行一个字符串 xff08 只包含小写字母 xff0c 长度不超过100 xff09 xff1b 输出一行一个字符串 例
  • 笔记 FreeRtos任务创建失败原因

    问题 使用NXP的S32芯片开发 xff0c 环境是S32DS 2018 xff0c 创建了三个任务 xff0c 最后发现只有一个任务在运行 找问题 S32DS自带了Freertos的分析调试工具 xff0c 打开后可以显示任务的状态 xf
  • 3.提升不同专业能力的差别?

    有段时间没写博客了 今天来谈谈最近工作的一些感悟 首先 我觉得工资和个人能力是成正相关的 这应该是是所有人都认同的吧 如果工资是一个函数的话 也可以说 工资 Y 是一个与个人能力 X 有关的一次函数Y aX b 方然我们不能忽略行业之间的差
  • 网络通讯学习(1)---TCP通讯

    TCP IP四层模型 UDP TCP协议 TCP xff08 The Transmission Control Protocol xff09 xff1a 传输控制协议 UDP TCP协议都属于传输层协议 xff0c 都位于IP协议以上 xf