《TCP/IP网络编程》学习笔记 | Chapter 1:理解网络编程和套接字
《TCP/IP网络编程》学习笔记 | Chapter 1:理解网络编程和套接字
- 《TCP/IP网络编程》学习笔记 | Chapter 1:理解网络编程和套接字
- 基本概念
- 服务端
- 客户端
- 基于 Linux 平台的 "Hello world!" 服务端和客户端
- 基于 Linux 的文件操作
- 打开文件
- 关闭文件
- 写文件
- 读文件
- 基于 Windows 平台的实现
- Winsock 的初始化
- 注销 Winsock 相关库
- 基于 Windows 的套接字相关函数
- 创建基于 Windows 的服务端和客户端
- 基于 Windows 的 I/O 函数
- 习题
- (1)套接字在网络编程中的作用是什么?为什么称它为套接字?
- (2)在服务器端创建套接字后,会依次调用listen函数和accept函数。请比较并说明两者作用。
- (3)Linux中,对套接字数据进行I/O时可以直接使用I/O相关函数;而在Windows中则不可以。原因为何?
- (4)创建套接字后一般会给它分配地址,为什么?为了完成地址分配需要调用哪些函数?
- (5)Linux中的文件描述符与Windows的句柄实际上非常类似。请以套接字为对象说明他们的含义。
- (6)底层文件I/O函数与ANSI标准定义的文件I/O函数之间有何区别?
《TCP/IP网络编程》学习笔记 | Chapter 1:理解网络编程和套接字
基本概念
网络编程是什么?
编写程序使两台联网的计算机相互交换数据。
服务端
步骤 1:创建套接字
int socket(int domain, int type, int protocol);
成功时返回文件描述符,失败时返回-1。
步骤 2:绑定IP地址和端口号
int bind(int socket, const struct sockaddr *address, socklen_t address_len);
成功时返回0,失败时返回-1
步骤 3:使转化为可接受请求状态
int listen(int sockfd, int backlog);
成功时返回文件描述符,失败时返回-1。
步骤 4:受理请求连接
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
成功时返回文件描述符,失败时返回-1。
客户端
步骤 1:创建socket
步骤 2:发起连接请求
int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
成功时返回0,失败返回-1。
基于 Linux 平台的 “Hello world!” 服务端和客户端
服务端程序:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>void error_handling(char* message);int main(int argc,char* argv[])
{int sock;struct sockaddr_in serv_addr;char message[30];int str_len;if(argc!=3){printf("Usage:%s <IP> <port>\n",argv[0]);exit(1);}sock = socket(PF_INET,SOCK_STREAM,0);if(sock==-1){error_handling("socket() error!");}memset(&serv_addr,0,sizeof(serv_addr));serv_addr.sin_family = AF_INET;serv_addr.sin_addr.s_addr = inet_addr(argv[1]);serv_addr.sin_port=htons(atoi(argv[2]));if(connect(sock,(struct sockaddr*)&serv_addr,sizeof(serv_addr))==-1){error_handling("connect() error!");}str_len = read(sock,message,sizeof(message)-1);if(str_len==-1){error_handling("read() error!");}printf("Message from server:%s \n",message);close(sock);return 0;
}void error_handling(char* message)
{fputs(message,stderr);fputc('\n',stderr);exit(1);
}
客户端程序:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>void error_handling(char* message);int main(int argc,char* argv[])
{int sock;struct sockaddr_in serv_addr;char message[30];int str_len;if(argc!=3){printf("Usage:%s <IP> <port>\n",argv[0]);exit(1);}sock = socket(PF_INET,SOCK_STREAM,0);if(sock==-1){error_handling("socket() error!");}memset(&serv_addr,0,sizeof(serv_addr));serv_addr.sin_family = AF_INET;serv_addr.sin_addr.s_addr = inet_addr(argv[1]);serv_addr.sin_port=htons(atoi(argv[2]));if(connect(sock,(struct sockaddr*)&serv_addr,sizeof(serv_addr))==-1){error_handling("connect() error!");}str_len = read(sock,message,sizeof(message)-1);if(str_len==-1){error_handling("read() error!");}printf("Message from server:%s \n",message);close(sock);return 0;
}void error_handling(char* message)
{fputs(message,stderr);fputc('\n',stderr);exit(1);
}
基于 Linux 的文件操作
Linux中一切皆文件,socket自然也是文件。
每当生成文件或socket,操作系统都将返回分配给它们的整数(文件描述符),文件描述符只不过是为了方便的称呼操作系统创建的文件或socket而赋予的数。
分配给标准输入,输出及标准错误的文件描述符。
| 文件描述符 | 对象 |
|---|---|
| 0 | 标准输入 :Standard Input |
| 1 | 标准输出 :Standard Ouput |
| 2 | 标准错误 :Standard Error |
其他的文件描述符从3开始的。
打开文件
#include <sys/stat.h>
#include <fcntl.h>int open(const char *path, int fla);
成功时返回文件描述符,失败时返回-1。
参数:
-
path: 文件名的字符串地址
-
flag: 文件打开模式信息,如需传递多个参数,应通过 | 运算符组合。
| 打开模式 | 含义 |
|---|---|
| O_CREAT | 必要时创建文件 |
| O_TRUNC | 删除全部现有数据 |
| O_APPEND | 维持现有数据,保存到其后面 |
| O_RDONLY | 只读打开 |
| O_WRONLY | 只写打开 |
| O_RDWR | 读写打开 |
关闭文件
#include <unistd.h>int close(int fildes);
成功时返回0,失败时返回-1。
参数:
- fildes: 需要关闭的文件或socket的文件描述符
写文件
#include <unistd.h>ssize_t write(int fildes, const void *buf, size_t nbyte);
成功时返回写入的字节数,失败时返回-1。
参数:
-
fildes: 显示数据传输对象的文件描述符
-
buf:保存要传输数据的缓冲地址值
-
nbyte: 要传输数据的字节数
size_t : unsigned int,ssize_t:signed int,这些都是元数据类型,由操作系统定义,通过 typedef 声明。
示例程序:
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>void error_handling(char *message)
{fputs(message, stderr);fputc('\n', stderr);exit(1);
}int main(void)
{int fd;char buf[] = "Let's go!\n";fd = open("data.txt", O_CREAT | O_WRONLY | O_TRUNC);if (fd == 1)error_handling("open() error!");printf("file descriptor: %d\n", fd);if (write(fd, buf, sizeof(buf)) == -1)error_handling("write() error!");close(fd);return 0;
}
运行结果:

注意:Windows 端可以用 type 命令打印 txt 文件的内容。
读文件
#include <unistd.h>ssize_t read(int fildes, void *buf, size_t nbyte);
成功时返回接收的字节数(但遇到文件结尾则返回0),失败时返回-1。
参数:
-
fildes:显示数据接收对象的文件描述符
-
buf:要保存接收数据的缓冲地址值
-
nbytes:要接收数据的最大字节数
示例程序:
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>#define BUF_SIZE 100void error_handling(char *message)
{fputs(message, stderr);fputc('\n', stderr);exit(1);
}int main(void)
{int fd;char buf[BUF_SIZE];fd = open("data.txt", O_RDONLY);if (fd == -1)error_handling("open() error!");printf("file descriptor: %d\n", fd);if (read(fd, buf, BUF_SIZE) == -1)error_handling("read() error!");printf("file data: %s", buf);close(fd);return 0;
}
运行结果:

基于 Windows 平台的实现
Windows 套接字,简称 Winsock,大部分参考 BSD 系列 UNIX 套接字设计,和 Linux 套接字类似。
Winsock 的初始化
进行Winsock编程时,首先调用 WSAStartup 函数,设置程序中用到的Winsock版本,并初始化相应版本的库。
int WSAStartup(WORD wVersionRequested,LPWSADATA lpWSAData);
参数:
- wVersionRequested:Winsock版本信息
- lpWSAData:WSADATA结构体变量的地址值
Winsock中存在多个版本,应准备WORD(typedef unsigned int WORD;)类型的套接字版本信息,若版本为1.2,则1是主版本号,2是副版本号,应传递 0x0201
0x0201 高8位为副版本号,低8位为主版本号。这里借助 MAKEWORD 宏函数来传递版本信息号。
MAKEWORD(1,2); // 主版本号是1,副版本号是2,返回0x0201
int main(int argc,char* argv[])
{WSADATA wsaData;....if(WSAStartup(MAKEWORD(1,2), &wsaData) != 0){....}return 0;
}
注销 Winsock 相关库
#include <Winsock2.h>int WSACleanup(void);
成功时返回0,失败时返回 SOCKET_ERROR。
基于 Windows 的套接字相关函数
创建socket:
SOCKET socket(int af,int type,int protocol);
成功时返回套接字句柄(对应linux中的文件描述符),失败返回 INVALID_SOCKET。
绑定IP和端口号:
int bind(SOCKET s,const struct sockaddr* name,int namelen);
成功返回0,失败返回SOCKET_ERROR。
将服务端设置为可接受请求状态:
int listen(SOCKET s,int backlog);
成功返回0,失败返回SOCKET_ERROR。
受理请求连接(accept):
SOCKET accept(SOCKET s,struct sockaddr* addr,int* addrlen);
成功时返回套接字句柄,失败时返回INVALID_SOCKET。
从客户端发起请求连接:
int connect(SOCKET s,const struct sockaddr* name,int namelen);
成功时返回0,失败时返回SOCKET_ERROR。
关闭套接字:
int closesocket(SOCKET s);
成功时返回0,失败时返回SOCKET_ERROR。
Windows中的句柄相当于linux中的文件描述符,但是Windows中的文件句柄和套接字句柄是有区别的。
创建基于 Windows 的服务端和客户端
服务端:
#include <stdio.h>
#include <stdlib.h>
#include <winsock2.h>void ErrorHanding(char *message)
{fputs(message, stderr);fputc('\n', stderr);exit(1);
}int main(int argc, char *argv[])
{WSADATA wsaData;SOCKET hServerSock, hClientSock;SOCKADDR_IN serverAddr, clientAddr;int szClientAddr;char message[] = "Hello World!";if (argc != 2){printf("Usage: %s <port>\n", argv[0]);exit(1);}if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)ErrorHanding("WSAStartup() error!");hServerSock = socket(PF_INET, SOCK_STREAM, 0);if (hServerSock == INVALID_SOCKET)ErrorHanding("socket() error!");memset(&serverAddr, 0, sizeof(serverAddr));serverAddr.sin_family = AF_INET;serverAddr.sin_addr.s_addr = htonl(INADDR_ANY);serverAddr.sin_port = htons(atoi(argv[1]));if (bind(hServerSock, (SOCKADDR *)&serverAddr, sizeof(serverAddr)) == SOCKET_ERROR)ErrorHanding("bind() error!");if (listen(hServerSock, 5) == SOCKET_ERROR)ErrorHanding("listen() error!");szClientAddr = sizeof(clientAddr);hClientSock = accept(hServerSock, (SOCKADDR *)&clientAddr, &szClientAddr);if (hClientSock == INVALID_SOCKET)ErrorHanding("accept() error!");send(hClientSock, message, sizeof(message), 0);closesocket(hClientSock);closesocket(hServerSock);WSACleanup();return 0;
}
客户端:
#include <stdio.h>
#include <stdlib.h>
#include <winsock2.h>void ErrorHanding(char *message)
{fputs(message, stderr);fputc('\n', stderr);exit(1);
}int main(int argc, char *argv[])
{WSADATA wsaData;SOCKET hSocket;SOCKADDR_IN serverAddr;char message[30];int strLen;if (argc != 3){printf("Usage: %s <IP> <port>\n", argv[0]);exit(1);}if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)ErrorHanding("WSAStartup() error!");hSocket = socket(PF_INET, SOCK_STREAM, 0);if (hSocket == INVALID_SOCKET)ErrorHanding("socket() error!");memset(&serverAddr, 0, sizeof(serverAddr));serverAddr.sin_family = AF_INET;serverAddr.sin_addr.s_addr = inet_addr(argv[1]);serverAddr.sin_port = htons(atoi(argv[2]));if (connect(hSocket, (SOCKADDR *)&serverAddr, sizeof(serverAddr)) == SOCKET_ERROR)ErrorHanding("connect() error!");strLen = recv(hSocket, message, sizeof(message) - 1, 0);if (strLen == -1)ErrorHanding("recv() error!");printf("Message from server: %s\n", message);closesocket(hSocket);WSACleanup();return 0;
}
编译遇到报错:

参考 【三种解决方法】undefined reference to `__imp_WSAStartup‘ 给出的解决办法,手动添加编译参数 -lwsock32:
gcc hello_server_win.c -lwsock32 -o hServerWingcc hello_client_win.c -lwsock32 -o hClientWin
编译就可以成功了:

我们运行服务端程序,监听 9190 端口:
hServerWin 9190
再运行客户端程序:
hClientWin 127.0.0.1 9190
得到输出:
Message from server: Hello World!
基于 Windows 的 I/O 函数
Linux中socket也是文件,因此可以通过文件I/O函数read和write进行数据传输。而Windows严格区分文件I/O函数和套接字I/O函数。
int send(SOCKET s,const char* buf,int len,int flags);
成功时返回传输字节数,失败时返回SOCKET_ERROR。
参数:
- s:表示数据传输对象连接的套接字句柄值
- buf:保存待传输数据的缓冲地址值
- len:要传输的字节数
- flags:传输数据时用到的多种选项信息
int recv(SOCKET s, const char* buf, int len, int flags);
成功时返回接收的字节数(收到EOF时为0),失败返回SOCKET_ERROR。
- s:表示数据接收对象连接的套接字句柄值
- buf:保存待接收数据的缓冲地址值
- len:要接收的字节数
- flags:接收数据时用到的多种选项信息
习题
(1)套接字在网络编程中的作用是什么?为什么称它为套接字?
网络编程就是编写程序让两台联网的计算机相互交换数据。在我们不需要考虑物理连接的情况下,我们只需要考虑如何编写传输软件。操作系统提供了名为“套接字”,套接字是网络传输传输用的软件设备。
socket英文原意是插座,我们把插头插到插座上就能从电网获得电力供给,同样,为了与远程计算机进行数据传输,需要连接到Internet,而变成中的“套接字”就是用来连接该网络的工具。
(2)在服务器端创建套接字后,会依次调用listen函数和accept函数。请比较并说明两者作用。
listen:将套接字转为可接受连接方式(监听套接字)
accept:受理连接请求,并且在没有连接请求的情况调用该函数,不会返回(阻塞)。直到有连接请求为止。二者存在逻辑上的先后关系。
(3)Linux中,对套接字数据进行I/O时可以直接使用I/O相关函数;而在Windows中则不可以。原因为何?
Linux把套接字也看作是文件,所以可以用文件I/O相关函数;而Windows要区分套接字和文件,所以设置了特殊的函数。
(4)创建套接字后一般会给它分配地址,为什么?为了完成地址分配需要调用哪些函数?
要在网络上区分来自不同机器的套接字,所以需要地址信息。分配地址是通过bind()函数实现。
(5)Linux中的文件描述符与Windows的句柄实际上非常类似。请以套接字为对象说明他们的含义。
Linux的文件描述符是为了区分指定文件而赋予文件的整数值(相当于编号)。Windows的文件描述符其实也是套接字的整数值,其目的也是区分指定套接字。
(6)底层文件I/O函数与ANSI标准定义的文件I/O函数之间有何区别?
- ANSI标准定义的输入、输出函数是与操作系统(内核)无关的以C标准写成的函数;相反,底层文件I/O函数是操作系统直接提供的。
- 标准I/O分为全缓冲,行缓冲,不缓冲三种形式;文件I/O为不带缓冲的I/O。
- 文件I/O主要针对文件操作,它操作的是文件描述符;标准I/O针对的是控制台,它操作的是字符流。对于不同设备得特性不一样,必须有不同API访问才最高效。
相关文章:
《TCP/IP网络编程》学习笔记 | Chapter 1:理解网络编程和套接字
《TCP/IP网络编程》学习笔记 | Chapter 1:理解网络编程和套接字 《TCP/IP网络编程》学习笔记 | Chapter 1:理解网络编程和套接字基本概念服务端客户端 基于 Linux 平台的 "Hello world!" 服务端和客户端基于 Linux 的文件操作打开文件关闭文件…...
服务端监控工具:Nmon使用方法
在性能测试过程中,对服务端的各项资源使用情况进行监控是很重要的一环。这篇博客,介绍下服务端监控工具:nmon的使用方法。 一、认识nmon 1、简介 nmon是一种在AIX与各种Linux操作系统上广泛使用的监控与分析工具,它能在系统运行…...
Java中的线程安全问题(如果想知道Java中有关线程安全问题的基本知识,那么只看这一篇就足够了!)
前言:多线程编程已经广泛开始使用,其可以充分利用系统资源来提升效率,但是线程安全问题也随之出现,它直接影响了程序的正确性和稳定性,需要对其进行深入的理解与解决。 ✨✨✨这里是秋刀鱼不做梦的BLOG ✨✨✨想要了解…...
基础设施即代码(IaC)在Python自动化运维中的应用探讨
基础设施即代码(IaC)在Python自动化运维中的应用探讨 目录 🌐 IaC概念与工具介绍🐍 使用Python实现基础设施自动化📦 版本控制与基础设施管理的最佳实践🔄 部署环境的一致性与可复现性 1. 🌐 …...
浅谈路由器
路由器是一种网络设备,它在网络中起着至关重要的作用,主要功能包括: 1、数据转发:路由器的主要任务是将数据包从一个网络转发到另一个网络。它根据数据包的目的地址来决定将数据包发送到哪个网络。 2、路径选择:路由器…...
openGauss数据库-头歌实验1-1 初识openGauss
一、历史与特性 任务描述 本关任务:了解openGauss的发展历史以及相关特性。 相关知识 为了完成本关任务,你需要掌握:1.openGauss的发展历程,2.openGauss的功能特性。 发展历程 2019年9月19日在华为全联接大会上,…...
QT找不到ffmpeg链接库解决方法
error: undefined reference to avformat_network_init() 一个神奇的报错,查了很久,检查步骤: 1、检查了 pro工程文件 2、链接库的真实性和正确性 在main.cpp中调用没有报错,在其它cpp文件中调用就报错。 破案了,…...
消息队列-Rabbitmq(消息发送,消息接收)
将来我们开发业务功能的时候,肯定不会在控制台收发消息,而是应该基于编程的方式。由于RabbitMQ采用了AMQP协议,因此它具备跨语言的特性。任何语言只要遵循AMQP协议收发消息,都可以与RabbitMQ交互。并且RabbitMQ官方也提供了各种不…...
2、顶点着色器之视图矩阵
1、作用:将物体从世界坐标系转换到相机坐标系,相当于从世界坐标系转换到相机的局部(本地)坐标系。 2、基于LookAt函数的视图矩阵: 相机位置eye:(ex,ey,ez),世界坐标系下的位置 目标位置center:(cx,cy,cz…...
crontab实现2026年开始每个月1号执行一次
要在 crontab 中设置一个任务,使其从 2026 年开始每个月的 1 号执行一次,可以使用以下格式: 0 0 1 * * <你的命令>这条规则的解释如下: 0 0:表示在每个月的 1 号的零点(00:00)执行。1&a…...
计算机网络803-(5)运输层
目录 一.运输层的两个主要协议:TCP 与 UDP 1.TCP/IP 的运输层有两个不同的协议: 2.端口号(protocol port number) (1)软件端口与硬件端口 (2)TCP 的端口 (3)三类端口 二.用户…...
八 MyBatis中接口代理机制及使用
八、MyBatis中接口代理机制及使用 实际上,第七章所讲内容mybatis内部已经实现了。直接调用以下代码即可获取dao接口的代理类: AccountDao accountDao (AccountDao)sqlSession.getMapper(AccountDao.class);使用以上代码的前提是:AccountMa…...
【解决】Ubuntu18.04 卸载python之后桌面异常且终端无法打开,重启后进入tty1,没有图形化界面
我因为python版本太过于混乱 (都是为了学习os) ,3.6—3.9版本我都安装了,指向关系也很混乱,本着“重装是最不会乱”的原则,我把全部版本都卸载了。然后装了3.9 发现终端打不开了,火狐浏览器的图…...
OpenEmbedded、yocto和poky是什么关系?
Yocto项目是基于OpenEmbedded构建系统发展而来的。Yocto采用了OpenEmbedded的许多核心概念和工具,比如BitBake构建工具。BitBake在这两个系统中都是用于解析和处理recipes文件,这些recipes文件包含了软件包构建的指令、依赖关系、安装步骤等内容。 它们…...
记录页面——一个蛮好看的登录页(uni-app)
效果图 <template><view class"container"><view class"flex-col login-box"><view class"flex-col" style"width: 80%"><view class"flex-col"><text class"welcome-text-font&qu…...
Android文件选择器[超级轻量级FilePicker测试没有问题][挣扎解决自带文件管理器获取不到绝对地址问题而是返回msf%3A1000038197]
超级轻量级FilePicker测试没有问题 本文摘录于:https://blog.csdn.net/gitblog_00365/article/details/141449437只是做学习备份之用,绝无抄袭之意,有疑惑请联系本人! 今天真的是发了疯的找文件管理器,因为调用系统自带的文件管理…...
【论文速读】| RED QUEEN: 保护大语言模型免受隐蔽多轮越狱攻击
基本信息 原文标题:RED QUEEN: Safeguarding Large Language Models against Concealed Multi-Turn Jailbreaking 原文作者:Yifan Jiang, Kriti Aggarwal, Tanmay Laud, Kashif Munir, Jay Pujara, Subhabrata Mukherjee 作者单位:Hippocr…...
39.第二阶段x86游戏实战2-HOOK实现主线程调用
免责声明:内容仅供学习参考,请合法利用知识,禁止进行违法犯罪活动! 本次游戏没法给 内容参考于:微尘网络安全 本人写的内容纯属胡编乱造,全都是合成造假,仅仅只是为了娱乐,请不要…...
wordpress argon主题美化方面
1、页面前端额外CSS: /*字体*/ font-face {font-family: myFont1; src:url(https://blog.yangmumu.com/css/fonts/Dancing.ttf) ;font-display: swap; } font-face {font-family: myFont2; src:url(https://blog.yangmumu.com/css/fonts/Regular.ttf) ;font-displa…...
qt QRadioButton详解
QRadioButton 是一个可以切换选中(checked)或未选中(unchecked)状态的选项按钮。单选按钮通常呈现给用户一个“多选一”的选择,即在一组单选按钮中,一次只能选中一个按钮。 重要方法 QRadioButton(QWidget…...
云计算——弹性云计算器(ECS)
弹性云服务器:ECS 概述 云计算重构了ICT系统,云计算平台厂商推出使得厂家能够主要关注应用管理而非平台管理的云平台,包含如下主要概念。 ECS(Elastic Cloud Server):即弹性云服务器,是云计算…...
进程地址空间(比特课总结)
一、进程地址空间 1. 环境变量 1 )⽤户级环境变量与系统级环境变量 全局属性:环境变量具有全局属性,会被⼦进程继承。例如当bash启动⼦进程时,环 境变量会⾃动传递给⼦进程。 本地变量限制:本地变量只在当前进程(ba…...
Leetcode 3576. Transform Array to All Equal Elements
Leetcode 3576. Transform Array to All Equal Elements 1. 解题思路2. 代码实现 题目链接:3576. Transform Array to All Equal Elements 1. 解题思路 这一题思路上就是分别考察一下是否能将其转化为全1或者全-1数组即可。 至于每一种情况是否可以达到…...
高等数学(下)题型笔记(八)空间解析几何与向量代数
目录 0 前言 1 向量的点乘 1.1 基本公式 1.2 例题 2 向量的叉乘 2.1 基础知识 2.2 例题 3 空间平面方程 3.1 基础知识 3.2 例题 4 空间直线方程 4.1 基础知识 4.2 例题 5 旋转曲面及其方程 5.1 基础知识 5.2 例题 6 空间曲面的法线与切平面 6.1 基础知识 6.2…...
【Java_EE】Spring MVC
目录 Spring Web MVC 编辑注解 RestController RequestMapping RequestParam RequestParam RequestBody PathVariable RequestPart 参数传递 注意事项 编辑参数重命名 RequestParam 编辑编辑传递集合 RequestParam 传递JSON数据 编辑RequestBody …...
在WSL2的Ubuntu镜像中安装Docker
Docker官网链接: https://docs.docker.com/engine/install/ubuntu/ 1、运行以下命令卸载所有冲突的软件包: for pkg in docker.io docker-doc docker-compose docker-compose-v2 podman-docker containerd runc; do sudo apt-get remove $pkg; done2、设置Docker…...
Maven 概述、安装、配置、仓库、私服详解
目录 1、Maven 概述 1.1 Maven 的定义 1.2 Maven 解决的问题 1.3 Maven 的核心特性与优势 2、Maven 安装 2.1 下载 Maven 2.2 安装配置 Maven 2.3 测试安装 2.4 修改 Maven 本地仓库的默认路径 3、Maven 配置 3.1 配置本地仓库 3.2 配置 JDK 3.3 IDEA 配置本地 Ma…...
算法岗面试经验分享-大模型篇
文章目录 A 基础语言模型A.1 TransformerA.2 Bert B 大语言模型结构B.1 GPTB.2 LLamaB.3 ChatGLMB.4 Qwen C 大语言模型微调C.1 Fine-tuningC.2 Adapter-tuningC.3 Prefix-tuningC.4 P-tuningC.5 LoRA A 基础语言模型 A.1 Transformer (1)资源 论文&a…...
Docker 本地安装 mysql 数据库
Docker: Accelerated Container Application Development 下载对应操作系统版本的 docker ;并安装。 基础操作不再赘述。 打开 macOS 终端,开始 docker 安装mysql之旅 第一步 docker search mysql 》〉docker search mysql NAME DE…...
嵌入式学习笔记DAY33(网络编程——TCP)
一、网络架构 C/S (client/server 客户端/服务器):由客户端和服务器端两个部分组成。客户端通常是用户使用的应用程序,负责提供用户界面和交互逻辑 ,接收用户输入,向服务器发送请求,并展示服务…...
