转自 https://edu.csdn.net/lecturer/505 朱老师物联网大讲堂
《9.linux网络编程实践》

第一部分、章节目录
3.9.1.linux网络编程框架
3.9.2.TCP协议的学习1
3.9.3.TCP协议的学习2
3.9.4.socket编程接口介绍
3.9.5.IP地址格式转换函数实践
3.9.6.soekct实践编程1
3.9.7.soekct实践编程2
3.9.8.socket实践编程3
3.9.9.socket编程实践4

第二部分、章节介绍
3.9.1.linux网络编程框架
本节讲述网络编程的框架,分层思想和TCP/IP协议的介绍,BS架构和CS架构的介绍等。
3.9.2.TCP协议的学习1
本节详细介绍TCP协议的特点,其中重点讲述了TCP协议保证实现可靠传输的机制。
3.9.3.TCP协议的学习2
本节接上节继续讲解TCP协议,主要讲了TCP协议建立连接和关闭连接时的握手方法,最后讲了使用TCP来实现的常见应用层协议。
3.9.4.socket编程接口介绍
本节介绍linux API中与网络编程相关的接口函数,后面的实战编程中都要用到这些函数。
3.9.5.IP地址格式转换函数实践
本节通过代码实践来给大家演示IP地址格式转换的几个函数
3.9.6.soekct实践编程1
本节开始编写基于TCP的客户端和服务器连接通信程序
3.9.7.soekct实践编程2
本节接上节继续编写,并且已经实现客户端和服务器的连接。
3.9.8.socket实践编程3
本节实现客户端和服务器之间的任意发送和接收、反复发送接收等功能
3.9.9.socket编程实践4
本节通过定义一个简单的应用层协议,来向大家介绍TCP连接建立后如何通过应用层协议来实现业务逻辑。

第三部分、随堂记录
3.9.1.linux网络编程框架
3.9.1.1、网络是分层的
(1)OSI 7层模型
(2)网络为什么要分层
(3)网络分层的具体表现
3.9.1.2、TCP/IP协议引入
(1)TCP/IP协议是用的最多的网络协议实现
(2)TCP/IP分为4层,对应OSI的7层
(3)我们编程时最关注应用层,了解传输层,网际互联层和网络接入层不用管
3.9.1.3、BS和CS
(1)CS架构介绍(client server,客户端服务器架构)
(2)BS架构介绍(broswer server,浏览器服务器架构)

3.9.2.TCP协议的学习1
3.9.2.1、关于TCP理解的重点
(1)TCP协议工作在传输层,对上服务socket接口,对下调用IP层
(2)TCP协议面向连接,通信前必须先3次握手建立连接关系后才能开始通信。
(3)TCP协议提供可靠传输,不怕丢包、乱序等。
3.9.2.2、TCP如何保证可靠传输
(1)TCP在传输有效信息前要求通信双方必须先握手,建立连接才能通信
(2)TCP的接收方收到数据包后会ack给发送方,若发送方未收到ack会丢包重传
(3)TCP的有效数据内容会附带校验,以防止内容在传递过程中损坏
(4)TCP会根据网络带宽来自动调节适配速率(滑动窗口技术)
(5)发送方会给各分割报文编号,接收方会校验编号,一旦顺序错误即会重传。

3.9.3.TCP协议的学习2
3.9.3.1、TCP的三次握手
(1)建立连接需要三次握手
(2)建立连接的条件:服务器listen时客户端主动发起connect
3.9.3.2、TCP的四次握手
(3)关闭连接需要四次握手
(4)服务器或者客户端都可以主动发起关闭
注:这些握手协议已经封装在TCP协议内部,socket编程接口平时不用管
3.9.3.3、基于TCP通信的服务模式
(1)具有公网IP地址的服务器(或者使用动态IP地址映射技术)
(2)服务器端socket、bind、listen后处于监听状态
(3)客户端socket后,直接connect去发起连接。
(4)服务器收到并同意客户端接入后会建立TCP连接,然后双方开始收发数据,收发时是双向的,而且双方均可发起
(5)双方均可发起关闭连接
3.9.3.4、常见的使用了TCP协议的网络应用
(1)http、ftp
(2)QQ服务器
(3)mail服务器

3.9.4.socket编程接口介绍
3.9.4.1、建立连接
(1)socket。socket函数类似于open,用来打开一个网络连接,如果成功则返回一个网络文件描述符(int类型),之后我们操作这个网络连接都通过这个网络文件描述符。
(2)bind
(3)listen
(4)connect
3.9.4.3、发送和接收
(1)send和write
(2)recv和read
3.9.4.4、辅助性函数
(1)inet_aton、inet_addr、inet_ntoa
(2)inet_ntop、inet_pton
3.9.4.5、表示IP地址相关数据结构
(1)都定义在 netinet/in.h
(2)struct sockaddr,这个结构体是网络编程接口中用来表示一个IP地址的,注意这个IP地址是不区分IPv4和IPv6的(或者说是兼容IPv4和IPv6的)
(3)typedef uint32_t in_addr_t; 网络内部用来表示IP地址的类型
(4)struct in_addr
{
in_addr_t s_addr;
};
(5)

struct sockaddr_in{__SOCKADDR_COMMON (sin_);in_port_t sin_port;                 /* Port number.  */struct in_addr sin_addr;            /* Internet address.  *//* Pad to size of `struct sockaddr'.  */unsigned char sin_zero[sizeof (struct sockaddr) -__SOCKADDR_COMMON_SIZE -sizeof (in_port_t) -sizeof (struct in_addr)];};

(6)struct sockaddr 这个结构体是linux的网络编程接口中用来表示IP地址的标准结构体,bind、connect等函数中都需要这个结构体,这个结构体是兼容IPV4和IPV6的。在实际编程中这个结构体会被一个struct sockaddr_in或者一个struct sockaddr_in6所填充。

3.9.5.IP地址格式转换函数实践
3.9.5.1、inet_addr、inet_ntoa、inet_aton
3.9.5.2、inet_pton、inet_ntop

#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>#define IPADDR  "192.168.1.102"// 0x66        01  a8      c0
// 102      1   168     192
// 网络字节序,其实就是大端模式int main(void)
{struct in_addr addr = {0};char buf[50] = {0};addr.s_addr = 0x6703a8c0;inet_ntop(AF_INET, &addr, buf, sizeof(buf));printf("ip addr = %s.\n", buf);/*  // 使用inet_pton来转换int ret = 0;struct in_addr addr = {0};ret = inet_pton(AF_INET, IPADDR, &addr);if (ret != 1){printf("inet_pton error\n");return -1;}printf("addr = 0x%x.\n", addr.s_addr);
*/  /*in_addr_t addr = 0;addr = inet_addr(IPADDR);printf("addr = 0x%x.\n", addr);      // 0x6601a8c0
*/  return 0;
}

3.9.6_7.soekct实践编程1_2
3.9.6.1、服务器端程序编写
(1)socket
(2)bind
(3)listen
(4)accept,返回值是一个fd,accept正确返回就表示我们已经和前来连接我的客户端之间建立了一个TCP连接了,以后我们就要通过这个连接来和客户端进行读写操作,读写操作就需要一个fd,这个fd就由accept来返回了。
注意:socket返回的fd叫做监听fd,是用来监听客户端的,不能用来和任何客户端进行读写;accept返回的fd叫做连接fd,用来和连接那端的客户端程序进行读写。
3.9.6.2、客户端程序编写
(1)socket
(2)connect

概念:端口号,实质就是一个数字编号,用来在我们一台主机中(主机的操作系统中)唯一的标识一个能上网的进程。端口号和IP地址一起会被打包到当前进程发出或者接收到的每一个数据包中。每一个数据包将来在网络上传递的时候,内部都包含了发送方和接收方的信息(就是IP地址和端口号),所以IP地址和端口号这两个往往是打包在一起不分家的。

#include <stdio.h>
#include <sys/socket.h>
#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
#include <arpa/inet.h>#define SERPORT     9003                        //服务器需要端口号,而客户端不需要提供
#define SERADDR     "192.168.129.128"     // ifconfig看到的
#define BACKLOG     100int main(void)
{// 第1步:先socket打开文件描述符int sockfd = -1, ret = -1, clifd = -1;socklen_t len = 0;struct sockaddr_in seraddr = {0};struct sockaddr_in cliaddr = {0};char ipbuf[30] = {0};sockfd = socket(AF_INET, SOCK_STREAM, 0);if (-1 == sockfd){perror("socket");return -1;}printf("socketfd = %d.\n", sockfd);// 第2步:bind绑定sockefd和当前电脑的ip地址&端口号seraddr.sin_family = AF_INET;        // 设置地址族为IPv4seraddr.sin_port = htons(SERPORT);    // 设置地址的端口号信息seraddr.sin_addr.s_addr = inet_addr(SERADDR); // 设置IP地址,inet_addr转换为网络字节序,解决数据的大小端问题ret = bind(sockfd, (const struct sockaddr *)&seraddr, sizeof(seraddr));if (ret < 0){perror("bind");return -1;}printf("bind success.\n");// 第三步:listen监听端口ret = listen(sockfd, BACKLOG);     if (ret < 0){perror("listen");return -1;}// 第四步:accept阻塞等待客户端接入clifd = accept(sockfd, (struct sockaddr *)&cliaddr, &len);printf("连接已经建立,client fd = %d.\n", ret);return 0;
}
#include <stdio.h>
#include <sys/socket.h>
#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
#include <arpa/inet.h>#define SERADDR     "192.168.129.128"     // 服务器开放给我们的IP地址和端口号
#define SERPORT     9003int main(void)
{// 第1步:先socket打开文件描述符int sockfd = -1, ret = -1;struct sockaddr_in seraddr = {0};struct sockaddr_in cliaddr = {0};// 第1步:socketsockfd = socket(AF_INET, SOCK_STREAM, 0);if (-1 == sockfd){perror("socket");return -1;}printf("socketfd = %d.\n", sockfd);// 第2步:connect链接服务器seraddr.sin_family = AF_INET;     // 设置地址族为IPv4seraddr.sin_port = htons(SERPORT);    // 设置地址的端口号信息seraddr.sin_addr.s_addr = inet_addr(SERADDR); // 设置IP地址ret = connect(sockfd, (const struct sockaddr *)&seraddr, sizeof(seraddr));if (ret < 0){perror("listen");return -1;}printf("connect result, ret = %d.\n", ret);return 0;
}
all:gcc server.c -o sergcc client.c -o cliclean:rm ser cli *.o

3.9.8.socket实践编程3
3.9.8.1、客户端发送&服务器接收
3.9.8.2、服务器发送&客户端接收
3.9.8.3、探讨:如何让服务器和客户端好好沟通
(1)客户端和服务器原则上都可以任意的发和收,但是实际上双方必须配合:client发的时候server就收,而server发的时候client就收
(2)必须了解到的一点:client和server之间的通信是异步的,这就是问题的根源
(3)解决方案:依靠应用层协议来解决。说白了就是我们server和client事先做好一系列的通信约定。

#include <stdio.h>
#include <sys/socket.h>
#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
#include <arpa/inet.h>
#include <string.h>#define SERADDR        "192.168.1.141"       // 服务器开放给我们的IP地址和端口号
#define SERPORT     9003char sendbuf[100];int main(void)
{// 第1步:先socket打开文件描述符int sockfd = -1, ret = -1;struct sockaddr_in seraddr = {0};struct sockaddr_in cliaddr = {0};// 第1步:socketsockfd = socket(AF_INET, SOCK_STREAM, 0);if (-1 == sockfd){perror("socket");return -1;}printf("socketfd = %d.\n", sockfd);// 第2步:connect链接服务器seraddr.sin_family = AF_INET;     // 设置地址族为IPv4seraddr.sin_port = htons(SERPORT);    // 设置地址的端口号信息seraddr.sin_addr.s_addr = inet_addr(SERADDR); // 设置IP地址ret = connect(sockfd, (const struct sockaddr *)&seraddr, sizeof(seraddr));if (ret < 0){perror("listen");return -1;}printf("成功建立连接\n");/*   // 建立连接之后就可以开始通信了strcpy(sendbuf, "hello world.");ret = send(sockfd, sendbuf, strlen(sendbuf), 0);printf("发送了%d个字符\n", ret);
*/
/*while (1){printf("请输入要发送的内容\n");scanf("%s", sendbuf);//printf("刚才输入的是:%s\n", sendbuf);ret = send(sockfd, sendbuf, strlen(sendbuf), 0);printf("发送了%d个字符\n", ret);}
*/ret = recv(sockfd, sendbuf, sizeof(sendbuf), 0);printf("成功接收了%d个字节\n", ret);printf("client发送过来的内容是:%s\n", sendbuf);return 0;
}
#include <stdio.h>
#include <sys/socket.h>
#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
#include <arpa/inet.h>
#include <string.h>#define SERPORT        9003
#define SERADDR     "192.168.1.141"       // ifconfig看到的
#define BACKLOG     100char recvbuf[100];int main(void)
{// 第1步:先socket打开文件描述符int sockfd = -1, ret = -1, clifd = -1;socklen_t len = 0;struct sockaddr_in seraddr = {0};struct sockaddr_in cliaddr = {0};char ipbuf[30] = {0};sockfd = socket(AF_INET, SOCK_STREAM, 0);if (-1 == sockfd){perror("socket");return -1;}printf("socketfd = %d.\n", sockfd);// 第2步:bind绑定sockefd和当前电脑的ip地址&端口号seraddr.sin_family = AF_INET;        // 设置地址族为IPv4seraddr.sin_port = htons(SERPORT);    // 设置地址的端口号信息seraddr.sin_addr.s_addr = inet_addr(SERADDR); // 设置IP地址ret = bind(sockfd, (const struct sockaddr *)&seraddr, sizeof(seraddr));if (ret < 0){perror("bind");return -1;}printf("bind success.\n");// 第三步:listen监听端口ret = listen(sockfd, BACKLOG);        // 阻塞等待客户端来连接服务器if (ret < 0){perror("listen");return -1;}// 第四步:accept阻塞等待客户端接入clifd = accept(sockfd, (struct sockaddr *)&cliaddr, &len);printf("连接已经建立,client fd = %d.\n", clifd);/*    // 建立连接之后就可以通信了// 客户端给服务器发ret = recv(clifd, recvbuf, sizeof(recvbuf), 0);printf("成功接收了%d个字节\n", ret);printf("client发送过来的内容是:%s\n", recvbuf);
*//*// 客户端反复给服务器发while (1){ret = recv(clifd, recvbuf, sizeof(recvbuf), 0);//printf("成功接收了%d个字节\n", ret);printf("client发送过来的内容是:%s\n", recvbuf); memset(recvbuf, 0, sizeof(recvbuf));}
*/// 服务器给客户端发strcpy(recvbuf, "hello world.");ret = send(clifd, recvbuf, strlen(recvbuf), 0);printf("发送了%d个字符\n", ret);return 0;
}
all:gcc server.c -o sergcc client.c -o cliclean:rm ser cli *.o -rf

3.9.9.socket编程实践4
3.9.9.1、自定义应用层协议第一步:规定发送和接收方法
(1)规定连接建立后由客户端主动向服务器发出1个请求数据包,然后服务器收到数据包后回复客户端一个回应数据包,这就是一个通信回合
(2)整个连接的通信就是由N多个回合组成的。

3.9.9.2、自定义应用层协议第二步:定义数据包格式
3.9.9.3、常用应用层协议:http、ftp······
3.9.9.4、UDP简介

#include <stdio.h>
#include <sys/socket.h>
#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
#include <arpa/inet.h>
#include <string.h>#define SERADDR        "192.168.1.141"       // 服务器开放给我们的IP地址和端口号
#define SERPORT     9003char sendbuf[100];
char recvbuf[100];#define CMD_REGISTER  1001    // 注册学生信息
#define CMD_CHECK       1002    // 检验学生信息
#define CMD_GETINFO     1003    // 获取学生信息#define STAT_OK            30      // 回复ok
#define STAT_ERR        31      // 回复出错了typedef struct commu
{char name[20];     // 学生姓名int age;         // 学生年龄int cmd;         // 命令码int stat;         // 状态信息,用来回复
}info;int main(void)
{// 第1步:先socket打开文件描述符int sockfd = -1, ret = -1;struct sockaddr_in seraddr = {0};struct sockaddr_in cliaddr = {0};// 第1步:socketsockfd = socket(AF_INET, SOCK_STREAM, 0);if (-1 == sockfd){perror("socket");return -1;}printf("socketfd = %d.\n", sockfd);// 第2步:connect链接服务器seraddr.sin_family = AF_INET;     // 设置地址族为IPv4seraddr.sin_port = htons(SERPORT);    // 设置地址的端口号信息seraddr.sin_addr.s_addr = inet_addr(SERADDR); // 设置IP地址ret = connect(sockfd, (const struct sockaddr *)&seraddr, sizeof(seraddr));if (ret < 0){perror("listen");return -1;}printf("成功建立连接\n");/*while (1){// 回合中第1步:客户端给服务器发送信息printf("请输入要发送的内容\n");scanf("%s", sendbuf);//printf("刚才输入的是:%s\n", sendbuf);ret = send(sockfd, sendbuf, strlen(sendbuf), 0);printf("发送了%d个字符\n", ret);// 回合中第2步:客户端接收服务器的回复memset(recvbuf, 0, sizeof(recvbuf));ret = recv(sockfd, recvbuf, sizeof(recvbuf), 0);//printf("成功接收了%d个字节\n", ret);printf("client发送过来的内容是:%s\n", recvbuf);// 回合中第3步:客户端解析服务器的回复,再做下一步定夺}
*/while (1){// 回合中第1步:客户端给服务器发送信息info st1;printf("请输入学生姓名\n");scanf("%s", st1.name);printf("请输入学生年龄");scanf("%d", &st1.age);st1.cmd = CMD_REGISTER;//printf("刚才输入的是:%s\n", sendbuf);ret = send(sockfd, &st1, sizeof(info), 0);printf("发送了1个学生信息\n");// 回合中第2步:客户端接收服务器的回复memset(&st1, 0, sizeof(st1));ret = recv(sockfd, &st1, sizeof(st1), 0);// 回合中第3步:客户端解析服务器的回复,再做下一步定夺if (st1.stat == STAT_OK){printf("注册学生信息成功\n");}else{printf("注册学生信息失败\n");}}return 0;
}
#include <stdio.h>
#include <sys/socket.h>
#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
#include <arpa/inet.h>
#include <string.h>#define SERPORT        9003
#define SERADDR     "192.168.1.141"       // ifconfig看到的
#define BACKLOG     100char recvbuf[100];#define CMD_REGISTER   1001    // 注册学生信息
#define CMD_CHECK       1002    // 检验学生信息
#define CMD_GETINFO     1003    // 获取学生信息#define STAT_OK            30      // 回复ok
#define STAT_ERR        31      // 回复出错了typedef struct commu
{char name[20];     // 学生姓名int age;         // 学生年龄int cmd;         // 命令码int stat;         // 状态信息,用来回复
}info;int main(void)
{// 第1步:先socket打开文件描述符int sockfd = -1, ret = -1, clifd = -1;socklen_t len = 0;struct sockaddr_in seraddr = {0};struct sockaddr_in cliaddr = {0};char ipbuf[30] = {0};sockfd = socket(AF_INET, SOCK_STREAM, 0);if (-1 == sockfd){perror("socket");return -1;}printf("socketfd = %d.\n", sockfd);// 第2步:bind绑定sockefd和当前电脑的ip地址&端口号seraddr.sin_family = AF_INET;        // 设置地址族为IPv4seraddr.sin_port = htons(SERPORT);    // 设置地址的端口号信息seraddr.sin_addr.s_addr = inet_addr(SERADDR); // 设置IP地址ret = bind(sockfd, (const struct sockaddr *)&seraddr, sizeof(seraddr));if (ret < 0){perror("bind");return -1;}printf("bind success.\n");// 第三步:listen监听端口ret = listen(sockfd, BACKLOG);        // 阻塞等待客户端来连接服务器if (ret < 0){perror("listen");return -1;}// 第四步:accept阻塞等待客户端接入clifd = accept(sockfd, (struct sockaddr *)&cliaddr, &len);printf("连接已经建立,client fd = %d.\n", clifd);// 客户端反复给服务器发while (1){info st;// 回合中第1步:服务器收ret = recv(clifd, &st, sizeof(info), 0);// 回合中第2步:服务器解析客户端数据包,然后干活,if (st.cmd == CMD_REGISTER){printf("用户要注册学生信息\n");printf("学生姓名:%s,学生年龄:%d\n", st.name, st.age);// 在这里服务器要进行真正的注册动作,一般是插入数据库一条信息// 回合中第3步:回复客户端st.stat = STAT_OK;ret = send(clifd, &st, sizeof(info), 0);}if (st.cmd == CMD_CHECK){}if (st.cmd == CMD_GETINFO){}}return 0;
}
all:gcc server.c -o sergcc client.c -o cliclean:rm ser cli *.o -rf

《9.linux网络编程实践》相关推荐

  1. ComeFuture英伽学院——2020年 全国大学生英语竞赛【C类初赛真题解析】(持续更新)

    视频:ComeFuture英伽学院--2019年 全国大学生英语竞赛[C类初赛真题解析]大小作文--详细解析 课件:[课件]2019年大学生英语竞赛C类初赛.pdf 视频:2020年全国大学生英语竞赛 ...

  2. ComeFuture英伽学院——2019年 全国大学生英语竞赛【C类初赛真题解析】大小作文——详细解析

    视频:ComeFuture英伽学院--2019年 全国大学生英语竞赛[C类初赛真题解析]大小作文--详细解析 课件:[课件]2019年大学生英语竞赛C类初赛.pdf 视频:2020年全国大学生英语竞赛 ...

  3. 信息学奥赛真题解析(玩具谜题)

    玩具谜题(2016年信息学奥赛提高组真题) 题目描述 小南有一套可爱的玩具小人, 它们各有不同的职业.有一天, 这些玩具小人把小南的眼镜藏了起来.小南发现玩具小人们围成了一个圈,它们有的面朝圈内,有的 ...

  4. 信息学奥赛之初赛 第1轮 讲解(01-08课)

    信息学奥赛之初赛讲解 01 计算机概述 系统基本结构 信息学奥赛之初赛讲解 01 计算机概述 系统基本结构_哔哩哔哩_bilibili 信息学奥赛之初赛讲解 02 软件系统 计算机语言 进制转换 信息 ...

  5. 信息学奥赛一本通习题答案(五)

    最近在给小学生做C++的入门培训,用的教程是信息学奥赛一本通,刷题网址 http://ybt.ssoier.cn:8088/index.php 现将部分习题的答案放在博客上,希望能给其他有需要的人带来 ...

  6. 信息学奥赛一本通习题答案(三)

    最近在给小学生做C++的入门培训,用的教程是信息学奥赛一本通,刷题网址 http://ybt.ssoier.cn:8088/index.php 现将部分习题的答案放在博客上,希望能给其他有需要的人带来 ...

  7. 信息学奥赛一本通 提高篇 第六部分 数学基础 相关的真题

    第1章   快速幂 1875:[13NOIP提高组]转圈游戏 信息学奥赛一本通(C++版)在线评测系统 第2 章  素数 第 3 章  约数 第 4 章  同余问题 第 5 章  矩阵乘法 第 6 章 ...

  8. 信息学奥赛一本通题目代码(非题库)

    为了完善自己学c++,很多人都去读相关文献,就比如<信息学奥赛一本通>,可又对题目无从下手,从今天开始,我将把书上的题目一 一的解析下来,可以做参考,如果有错,可以告诉我,将在下次解析里重 ...

  9. 信息学奥赛一本通(C++版) 刷题 记录

    总目录详见:https://blog.csdn.net/mrcrack/article/details/86501716 信息学奥赛一本通(C++版) 刷题 记录 http://ybt.ssoier. ...

  10. 最近公共祖先三种算法详解 + 模板题 建议新手收藏 例题: 信息学奥赛一本通 祖孙询问 距离

    首先什么是最近公共祖先?? 如图:红色节点的祖先为红色的1, 2, 3. 绿色节点的祖先为绿色的1, 2, 3, 4. 他们的最近公共祖先即他们最先相交的地方,如在上图中黄色的点就是他们的最近公共祖先 ...

最新文章

  1. 自动驾驶规划术语与搜索空间的几种方法
  2. 让linux启动更快的方法
  3. 2018python培训-python培训哪里比较好?
  4. 人工智能抢饭碗,你的工作还保得住吗?
  5. java面试题40 当编译并运行下面程序时会发生什么结果()
  6. 图数据库neo4j安装、neo4j使用
  7. idea怎么设置代码提示不区分大小写_IntelliJ IDEA 这样设置动图,棒极了!
  8. python的编程方式模块化_我的Python笔记·模块化编程(一)
  9. App中如何实现消息推送
  10. Python 测试驱动开发(四)测试及重构的目的(下)
  11. 时间复杂度、空间复杂度,如何”不复杂“地学?
  12. 解决keil5不支持Samsung 2440A等较旧型号Soc的方法
  13. java 链式写法_JAVA中实现链式操作(方法链)的简单例子
  14. 拆解一探电路设计:小米路由器3C拆解
  15. 可以作用c语言常量的是,正确的C语言常量是什么?
  16. 基于物联网技术的校园智慧消防管理平台-Susie 周
  17. Python 自然语言处理(基于jieba分词和NLTK)
  18. Quartus Prime下载地址(17.1Standard)
  19. mysql records_MySQL 基本操作 · LYF_Records
  20. 如何从零开始用PyTorch实现Chatbot?(附完整代码)

热门文章

  1. YOLOv4论文阅读笔记(一)
  2. 交换机端口镜像及Wireshake抓包
  3. 如何创建一个高颜值、高性能的可视化仪表盘,DevExpress Dashboard v20.1这些功能可以了解一下!
  4. python青果教务系统抢课_名额不够,技术来凑,利用Python实现教务系统强制性抢课...
  5. vue中ref、reactive和 toRefs toRef
  6. Python:小球反弹
  7. wifi信道就是频段吗?,频段带宽又是什么?
  8. linux看视频安装flash-解决慕课上播放时code7的问题
  9. 12【多线程、锁机制、lock锁】
  10. Python渗透测试编程技术--------身份认证攻击(一)