Linux网络编程:Socket套接字编程(Server服务器 Client客户端)

2023-11-04

文章目录:

一:定义和流程分析

1.定义

2.流程分析 

3.网络字节序

二:相关函数 

IP地址转换函数inet_pton inet_ntop(本地字节序 网络字节序)

socket函数(创建一个套接字)

bind函数(给socket绑定一个服务器地址结构(IP+port))

listen函数(设置最大连接数或者说能同时进行三次握手的最大连接数监听上限)

accept函数(阻塞监听等待客户端建立连接, 成功的话返回一个与客户端成功连接的socket文件描述符)

connect函数(使用现有的socket与服务器建立连接)

三:服务器模型和客户端模型的实现 

Server服务器的实现

Client客户端的实现


一:定义和流程分析

1.定义

定义:一个文件描述符指向一个套接字(该套接字内部由内核借助两个缓冲区实现)
         在通信过程中, 套接字一定是成对出现的
        一种文件类型,伪文件,不占用存储空间,可进行IO操作,可间接看做文件描述符使
        Socket本身有“插座”的意思
        在Linux环境下,用于表示进程间网络通信的特殊文件类型。本质为内核借助缓冲区形成的伪文件

    管道, 套接字, 块设备, 字符设备;
    套接字: 一个fd可以索引读写两个缓冲区;



套接字的作用
    套接字是网络通信中的一种端点,它提供了应用层进程利用网络协议交换数据的机制
    套接字可以用于不同主机上的应用进程之间进行双向通信,使得它们可以交换数据、同步连接状态、处理错误等

    在计算机系统中,套接字通常被实现为文件描述符,用于在网络上进行数据传输
    当应用程序打开一个套接字时,操作系统会为它分配一个唯一的文件描述符,以便于进程间通信

2.流程分析 

 

socket():创建一个套接字, 用fd索引

bind():绑定IP和port

listen():设置监听上限(同时与Server建立连接数)

accpet():阻塞监听客户端连接(传入一个上面创建的套接字, 传出一个连接的套接字)

在客户端中的connect()中绑定IP和port,并建立连接(阻塞)

3.网络字节序

小端法:(pc本地存储)	高位存高地址。低位存低地址。	int a = 0x12345678
大端法:(网络存储)	高位存低地址。低位存高地址。

htonl --> 本地--》 网络 (IP)			192.168.1.11 --> string --> atoi --> int --> htonl --> 网络字节序
htons --> 本地--》 网络 (port)
ntohl --> 网络--》 本地(IP)
ntohs --> 网络--》 本地(Port)

用库函数做网络字节序和主机字节序的转换

#include<arpa/inet.h>
uint32_t htonl(uint32_t hostlong);			//主要针对IP
uint16_t htons(uint16_t hostshort);			//主要针对port
uint32_t ntohl(uint32_t netlong);
uint16_t ntohs(uint16_t netshort);

二:相关函数 

IP地址转换函数inet_pton inet_ntop(本地字节序 网络字节序)

由于如192.168.45.2这种的IP地址为点分十进制表示,需要转化为uint32_t型,有现成的函数(IPv4和IPv6都可以转换) 

//本地字节序(string IP) ---> 网络字节序
int inet_pton(int af, const char *src, void *dst);		                   
	af:AF_INET、AF_INET6
	src:传入,IP地址(点分十进制)
	dst:传出,转换后的 网络字节序的 IP地址。 
	返回值:
		成功: 1
		异常: 0, 说明src指向的不是一个有效的ip地址。
		失败:-1


//网络字节序 ---> 本地字节序(string IP)
const char *inet_ntop(int af, const void *src, char *dst, socklen_t size);	
	af:AF_INET、AF_INET6
	src: 网络字节序IP地址
	dst:本地字节序(string IP)
	size: dst 的大小。
	返回值: 成功:dst、失败:NULL

socket函数(创建一个套接字)

#include <sys/socket.h>


int socket(int domain, int type, int protocol);		创建一个 套接字

    domain指定使用的协议(IPv4或IPv6)
	    AF_INET 这是大多数用来产生socket的协议,使用TCP或UDP来传输,用IPv4的地址
	    AF_INET6 与上面类似,不过是来用IPv6的地址
	    AF_UNIX 本地协议,使用在Unix和Linux系统上,一般都是当客户端和服务器在同一台及其上的时候使用

    type指定数据传输协议(流式或报式)
        SOCK_STREAM 这个协议是按照顺序的、可靠的、数据完整的基于字节流的连接。这是一个使用最多的socket类型,这个socket是使用TCP来进行传输。
	    SOCK_DGRAM 这个协议是无连接的、固定长度的传输调用。该协议是不可靠的,使用UDP来进行它的连接。
	    SOCK_SEQPACKET该协议是双线路的、可靠的连接,发送固定长度的数据包进行传输。必须把这个包完整的接受才能进行读取。
	    SOCK_RAW socket类型提供单一的网络访问,这个socket类型使用ICMP公共协议。(ping、traceroute使用该协议)
	    SOCK_RDM 这个类型是很少使用的,在大部分的操作系统上没有实现,它是提供给数据链路层使用,不保证数据包的顺序

    指定代表协议(一般默认传0)protocol: 0 
        流式以TCP为代表;
        报式以UDP为代表;

    返回值:返回指向新创建的socket的文件描述符
        成功:返回新套接字所对应文件描述符fd
        失败:返回-1并设置errno;

bind函数(给socket绑定一个服务器地址结构(IP+port))

#include <sys/socket.h>


 int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);		给socket绑定一个 地址结构 (IP+port)

	sockfd: socket文件描述符
		struct sockaddr_in servaddr;
		addr.sin_family = AF_INET;
		addr.sin_port = htons(8888);
		addr.sin_addr.s_addr = htonl(INADDR_ANY);

    addr: 构造出IP地址加端口号
        传入参数(struct sockaddr *)&addr

    addrlen: sizeof(addr) 地址结构的大小


	返回值:
		成功:0
		失败:返回-1, 设置errno

listen函数(设置最大连接数或者说能同时进行三次握手的最大连接数监听上限)

#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>


int listen(int sockfd, int backlog);        //设置同时与服务器建立连接的上限数(同时进行3次握手的客户端数量)

    sockfd:
        socket文件描述符

    backlog:上限数值。最大值 128
	    排队建立3次握手队列和刚刚建立3次握手队列的链接数和

    返回值:
		成功:0
		失败:-1 errno	

accept函数(阻塞监听等待客户端建立连接, 成功的话返回一个与客户端成功连接的socket文件描述符)

#include <sys/types.h> 		/* See NOTES */
#include <sys/socket.h>


int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);

    sockfd:
	    socket文件描述符

    addr:成功与Sever建立连接的那个**客户端**的地址结构;
	    传出参数,返回链接客户端地址信息(IP地址+端口号)

    addrlen:传入传出参数(值-结果),传入sizeof(addr)大小,函数返回时返回真正接收到地址结构体的大小	    
​	    socklen_t clit_addr_len=sizeof(addr);
​	    入: 传入addr的大小;
​	    出: 客户端addr的实际大小;

    返回值:    
​	    成功: 返回能与客户端进行通信的socket对应的文件描述符;
​	    失败: 返回-1并设置errno;



//我们的服务器程序结构是这样的
while (1) {
	cliaddr_len = sizeof(cliaddr);
	connfd = accept(listenfd, (struct sockaddr *)&cliaddr, &cliaddr_len);
	n = read(connfd, buf, MAXLINE);
	......
	close(connfd);
}

connect函数(使用现有的socket与服务器建立连接)

#include <sys/types.h> 					/* See NOTES */
#include <sys/socket.h>


int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);

    sockdf:socket文件描述符
    	struct sockaddr_in srv_addr;		// 服务器地址结构
		srv_addr.sin_family = AF_INET;
		srv_addr.sin_port = 9527 	跟服务器bind时设定的 port 完全一致。
		inet_pton(AF_INET, "服务器的IP地址",&srv_adrr.sin_addr.s_addr);
	    

    addr:
	    传入参数,指定服务器端地址信息,含IP地址和端口号

    addrlen:
	    传入参数,服务器地址结构的长度sizeof(addr)大小

    返回值:
	   ​	成功返回0;
​	    失败返回-1并设置errno;


如果不使用`bind()`函数绑定客户端的地址结构, 会采用**"隐式绑定"**;

三:服务器模型和客户端模型的实现 

Server服务器的实现

server:
	1. socket()	创建socket

	2. bind()	绑定服务器地址结构

	3. listen()	设置监听上限

	4. accept()	阻塞监听客户端连接

	5. read(fd)	读socket获取客户端数据

	6. 小--大写	toupper()

	7. write(fd)

	8. close();

代码逻辑

#include <stdio.h>
#include <ctype.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <pthread.h>
 
#define SERV_PORT 9527					//端口号
 
int main(int argc, char *argv[]){
    int link_fd=0;						//建立连接的socket文件描述符
    int connect_fd=0					//用于通信的文件描述符
    int ret=0;							//用于检查是否出错
    char buf[BUFSIZ];					//缓冲区
    char client_IP[1024]				//存入客户端IP字符串
    int num=0;							//读出的字节数
    /*服务器端地址结构*/
    struct sockaddr_in serv_addr;                   	 // 定义服务器地址结构 和 客户端地址结构
		serv_addr.sin_family=AF_INET;                    // IPv4
		serv_addr.sin_port=htons(SERV_PORT);             // 转为网络字节序的 端口号
		serv_addr.sin_addr.s_addr=htonl(INADDR_ANY);     // 获取本机任意有效IP
    
    /*成功与服务器建立连接的客户端地址结构*/
    struct sockaddr_in clint_addr;
    socklen_t clint_addr_len=sizeof(clint_addr);    	 // 获取客户端地址结构大小
        
 
 
 
    /*1.socket函数:创建用于建立连接的socket,返回的文件描述符存入link_fd*/
		//IPv4,按照顺序基于字节流的连接,指定代表协议
		link_fd=socket(AF_INET,SOCK_STREAM,0);		
		if(link_fd==-1)
			sys_err("socket error");
    
    /*2.bind函数:绑定服务器端的socket绑定地址结构(IP+port)*/
		//socket文件描述符link_fd,IP地址加端口号
		ret=bind(link_fd,(const struct sockaddr*)&serv_addr,sizeof(serv_addr));
		if(ret==-1)
			sys_err("bind error");
    
    /*3.listen函数:设定监听(连接)上线*/
    ret=listen(link_fd,128); 
    if(ret==-1)
        sys_err("listen error");
    
    /*4.accept函数:阻塞等待客户端建立连接*/
		//文件描述符,与Sever建立连接的客户端的地址结构,返回真正接收到地址结构体的大小
		connect_fd=accept(link_fd,(	struct sockaddr*)&clint_addr,&clint_addr_len);    
		if(connect_fd==-1)
			sys_err("accept error");
 
    /*建立连接后打印客户端的IP和端口号    获取客户端地址结构*/
        printf(
				"client IP:%s,client port:%d",  												//`client_IP`是前面定义的客户端IP字符串的缓冲区, 大小为1024           
				inet_ntop(AF_INET,&clint_addr.sin_addr.s_addr,client_IP,sizeof(client_IP)),		//网络字节序 ---> 本地字节序
				ntohs(clint_addr.sin_port)														//根据accept传出参数,获取客户端 ip 和 port
			  );           
    
    /*业务逻辑*/
    while(1){
        //5. read(fd)	读socket获取客户端数据
			num=read(connect_fd,buf,sizeof(buf));    // 读客户端数据
			write(STDOUT_FILENO,buf,num);            // 写到屏幕查看
 
        //6. 小--大写	toupper()
			for(i=0;i<num;i++)                       // 小写 -- 大写
				buf[i]=toupper(buf[i]);
 
        //7. write(fd)
			write(connect_fd,buf,num);               // 将大写,写回给客户端
 
        sleep(1);
    }
 
    
    //8. close()
		close(connect_fd);
		close(link_fd);
 
  
   	return 0;
}

测试命令 

`nc 127.0.0.1 9527`        //脑残命令: 向这个服务发送信息并打印回执

Client客户端的实现

client:
	1. socket()	创建socket

	2. connect();	与服务器建立连接

	3. write()	写数据到 socket

	4. read()	读转换后的数据

	5. 显示读取结果

	6. close()

代码逻辑

#include <stdio.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <pthread.h>
 
#define SERV_PORT 9527
 
/*错误处理函数*/
void sys_err(const char* str){
	perror(str);
	exit(1);
}
 
int main(int argc, char *argv[])){
	int client_fd=0;
	int ret=0;
	int num=0;
	int cnt=10;
	char buf[BUFSIZ];
 
	//connect的参数2填入服务器的文件描述符!
	struct sockaddr_in serv_addr;
		serv_addr.sin_family=AF_INET;
		serv_addr.sin_port=htons(SERV_PORT);
    

	// 本地字节序(string IP) ---> 网络字节序
	inet_pton(AF_INET,"127.0.0.1",(void*)&serv_addr.sin_addr.s_addr);
 
 
 
    /*1. 创建socket():客户端直接创建用于连接的套接字即可*/
		client_fd=socket(AF_INET,SOCK_STREAM,0);
		if(client_fd==-1)
			sys_err("socket error");
 
    /*2. connect():将客户端套接字与服务器地址结构连接起来*/
		ret=connect(client_fd,(struct sockaddr*)&serv_addr,sizeof(serv_addr));
		if(ret!=0)
			sys_err("connect error");
    
	//业务逻辑
	while(--cnt){
		
        //3. write()	写数据到 socket
			write(client_fd,"fuckyou\n",8);
		
        //4. read()	读转换后的数据。
			num=read(client_fd,buf,sizeof(buf));
 
        //5. 显示读取结果
			write(STDOUT_FILENO,buf,num);

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

Linux网络编程:Socket套接字编程(Server服务器 Client客户端) 的相关文章

  • python获取上传/下载速度

    我想在我的计算机上监控上传和下载速度 一个名为 conky 的程序已经在 conky conf 中执行了以下操作 Connection quality alignr wireless link qual perc wlan0 downspe
  • 使用 \r 并打印一些文本后如何清除控制台中的一行?

    对于我当前的项目 有一些代码很慢并且我无法使其更快 为了获得一些关于已完成 必须完成多少的反馈 我创建了一个进度片段 您可以在下面看到 当你看到最后一行时 sys stdout write r100 80 n I use 80覆盖最终剩余的
  • 在centos中安装sqlite3 dev和其他包

    我正在尝试使用 cpanel 在 centos 机器上安装 sqlite dev 和其他库 以便能够编译应用程序 我对 debian 比 centos 更熟悉 我知道我需要的库是 libsqlite3 dev libkrb5 dev lib
  • Linux 上的静态 Qt5 构建:部署时如何处理字体?

    我使用这些配置选项创建了 Qt 5 2 0 库的静态版本 Ubuntu 12 04 开源 确认许可 force pkg config 发布 静止的 前缀 home juzzlin qt5 无icu opengl桌面 无油嘴滑舌 辅助功能 n
  • 执行“minikube start”命令时出现问题

    malik malik minikube start minikube v1 12 0 on Ubuntu 18 04 Using the docker driver based on existing profile Starting c
  • 如何根据标签将单个 XML 文件拆分为多个

    我有一个带有标签的 XML 文件 我想像这样分割文件
  • 如何使用waf构建共享库?

    我想使用构建一个共享库waf http code google com p waf 因为它看起来比 GNU 自动工具更容易 更简洁 到目前为止 我实际上有几个与我开始编写的 wscript 有关的问题 VERSION 0 0 1 APPNA
  • 如何在 Linux 中使用 C 语言使用共享内存

    我的一个项目有点问题 我一直在试图找到一个有据可查的使用共享内存的例子fork 但没有成功 基本上情况是 当用户启动程序时 我需要在共享内存中存储两个值 当前路径这是一个char and a 文件名这也是char 根据命令参数 启动一个新进
  • Mac OS X 上的 /proc/self/cmdline / GetCommandLine 等效项是什么?

    如何在不使用 argc argv 的情况下访问 Mac OS X 上的命令行 在 Linux 上 我会简单地阅读 proc self cmdline or use GetCommandLine在 Windows 上 但我找不到 Mac OS
  • 为什么opencv videowriter这么慢?

    你好 stackoverflow 社区 我有一个棘手的问题 我需要你的帮助来了解这里发生了什么 我的程序从视频采集卡 Blackmagic 捕获帧 到目前为止 它工作得很好 同时我用 opencv cv imshow 显示捕获的图像 它也工
  • 使用 python 脚本更改 shell 中的工作目录

    我想实现一个用户态命令 它将采用其参数之一 路径 并将目录更改为该目录 程序完成后 我希望 shell 位于该目录中 所以我想实施cd命令 但需要外部程序 可以在 python 脚本中完成还是我必须编写 bash 包装器 Example t
  • Linux 为一组进程保留一个处理器(动态)

    有没有办法将处理器排除在正常调度之外 也就是说 使用sched setaffinity我可以指示线程应该在哪个处理器上运行 但我正在寻找相反的情况 也就是说 我想从正常调度中排除给定的处理器 以便只有已明确调度的进程才能在那里运行 我还知道
  • linux下如何从文本文件中获取值

    我有一些文本格式的文件 xxx conf 我在这个文件中有一些文本 disablelog 1 当我使用 grep r disablelog oscam conf 输出是 disablelog 1 但我只需要值1 请问你有什么想法吗 一种方法
  • 使用 gdb 调试 Linux 内核模块

    我想知道 API 在内核模块 中返回什么 从几种形式可以知道 这并不是那么简单 我们需要加载符号表来调试内核模块 所以我所做的就是 1 尝试找到内核模块的 text bss和 data段地址 2 在 gdb 中使用 add symbol f
  • 为什么同一个curl命令在windows和linux下输出不同的东西?

    为什么同样的curl o file https www link com 命令输出不同的东西 例如 如果我运行命令curl o source txt https www youtube com playlist list PLIx6Fwnp
  • 如何在文件中搜索多行模式?

    我需要找到包含特定字符串模式的所有文件 我想到的第一个解决方案是使用find管道与xargs grep find iname py xargs grep e YOUR PATTERN 但是 如果我需要查找跨越多行的模式 我就会陷入困境 因为
  • 使用awk将列中的值替换为txt文件中的另一个值

    我是 Linux 和 awk 脚本编写的新手 我有 tab delim txt 文件 如下所示 AAA 134 145 Sat 150 167 AAA 156 167 Sat 150 167 AAA 175 187 Sat 150 167
  • 如何在shell脚本中给出密码?

    在 shell 脚本文件中 我使用一些命令 例如scp and make install要求我输入密码 我运行一个 shell 脚本来编译一个大项目 一段时间后它会要求我输入密码才能使用scp 我需要等待该过程并在此之后提供密码 我只想通过
  • 在 scp 的简单函数包装中使用波形符 ~ 时出现问题

    我想放置一个简单的bash功能在我的 bashrc围绕着scp通过接受 源 参数和 目标 参数来命令 到目前为止已经尝试过 function send eval scp 1 user annoyingly long server name
  • 为 OpenWrt 编写和编译程序

    我有一个在 OpenWRT 下运行的具有 MIPS 架构的嵌入式设备 系统类型 MediaTek MT7628AN ver 1 eco 2机器 WRTnode2P 处理器 0CPU型号 MIPS 24KEc V5 5 我想通过我的电脑 ub

随机推荐

  • 【自然语言处理】关系抽取 —— SimpleRE 讲解

    SimpleRE 论文信息 标题 An Embarrassingly Simple Model for Dialogue Relation Extraction 作者 Fuzhao Xue 期刊 ICASSP 2022 发布时间与更新时间
  • 【Ubuntu】安装免费版Typora

    下载deb包 wget https file babudiu com f yXCL Typora Linux 0 11 18 amd64 deb 安装 sudo dpkg i Typora Linux 0 11 18 amd64 deb 参
  • 【蓝桥杯题解】特殊日期(判断合法日期模板)

    对于一个日期 我们可以计算出年份的各个数位上的数字之和 也可以分别计算月和日的各位数字之和 请问从 19001900 年 11 月 11 日至 99999999 年 1212 月 3131 日 总共有多少天 年份的数位数字之和等于月的数位数
  • centos 卸载程序

    1 查询软件列表 rpm qa grep 软件名 2 卸载软件 sudo yum remove 软件名
  • SQLite安装配置详细教程2023版

    前言 SQLite 是一款轻型的数据库 是遵守ACID的关系型数据库管理系统 它的设计目标是嵌入式的 而且已经在很多嵌入式产品中使用了它 它占用资源非常的低 它能够支持Windows Linux Unix等等主流的操作系统 同时能够跟很多程
  • 利用强化学习进行股票操作实战(三)

    与上一篇文章相同之处 对于交易策略 与上一篇文章相同 当发出买入指令时 一次性全部买入 当发出卖出指令时 一次性全部卖出 还没有添加加减仓操作 模型仍然用的是DQN模型 新增内容 在之前的基础上加入了交易手续费 印花税等 在强化学习这个领域
  • 基于FPGA驱动VGA显示图片的小问题

    学习VGA显示图片的过程中 遇到了一个小问题 我在显示屏上开了一个60x60的框 放了一张图片进去显示 但是最终的结果如下图所示 出现了一个竖黑边 看了看代码 分析了一下逻辑没问题 然而看这个显示那肯定是有问题的 然后仿真了一下看看 时序图
  • 在Vue2和Vue3中事件总线的使用与区别

    前提 在Vue升级到3 0版本后 事件总线使用的方式有些许改变 Vue2可以直接使用new Vue 在Vue3中 推荐使用mitt来帮助我们实现全局事件总线和局部事件总线 接下来让我们来对比2和3版本的使用和区别 Mitt是一个微型的 Ev
  • 可靠传输的运输层协议及编程实现

    在计算机网络中 运输层协议负责在通信实体之间提供可靠的数据传输 可靠传输意味着数据的发送方可以确保数据在传输过程中不会丢失 损坏 重复或无序到达接收方 本文将介绍一种常用的可靠传输协议 停等协议 并提供其简单的编程实现 停等协议 Stop
  • STM32 F103C8T6学习笔记4:时钟树、滴答计时器、定时器定时中断

    今日理解一下STM32F103 C8T6的时钟与时钟系统 滴答计时器 定时器计时中断的配置 文章提供原理 代码 测试工程下载 目录 时钟树与时钟系统 滴答计时器 定时器计时中断 测试结果 测试工程下载 时钟树与时钟系统 该系统介绍在 STM
  • “思维导图”常用的快捷键总结

    还记得老师上课说过 你们把那些贴来的东西放在自己的博客上就以为是自己的了吗 其实不然 我们有些时候过于追求是否做了 而没有考虑到做这个的意义何在 正如贾琳同学所说 不要为了做去做 而要将自己做过的东西变成自己所能够吸收的 变成自己前进的 汽
  • 面向组件编程之Unity 5.normalized不改变原向量,Normalize改变原向量

    using System Collections using System Collections Generic using UnityEngine public class TransformFeng2 MonoBehaviour Us
  • Android AlarmManager实现定时任务(也就是闹钟) 附Demo源码

    原文链接https www shanya world archives a7b639d4 html 创建定时任务 Android中的定时任务一般有两种实现方式 一种是使用 Java API 里提供的 Timer 类 一种是使用 Androi
  • 防恶意解析,禁止用IP访问网站的Apache设置+如何阻止网站被恶意反向代理访问

    一般来说 网站可以用域名和IP来访问 你的网站可以通过IP直接访问 本来这没什么问题 但是会有些隐患 由于搜索引擎也会收录你的IP地址的页面 所以同一个页面搜索引擎会重复收录 造成页面的权重不如单个收录高 域名恶意指向的可能 还记得去年还是
  • keepalived + mysql 双主

    在node2 node3上安装mysql并配置主主复制 初始化mysql root node2 mysqlkeepalived mysqld defaults file home mysqlkeepalived my cnf basedir
  • 使用python,dlib,OpenCV提取眼睛,鼻子,嘴唇及下颌

    使用python dlib OpenCV提取眼睛 鼻子 嘴唇及下颌 1 效果图 2 原理 3 源码 参考 上一篇博客中 我们了解了什么是面部标志 以及如何使用dlib OpenCV和Python检测它们 利用dlib的HOG SVM的形状预
  • vuecli启动的服务器位置,VUE启动流程vue-cli

    先后顺序 package json gt webpack dev conf js gt config js gt config index js gt index html gt App vue的export外的js代码 gt main j
  • C和C++安全编码笔记:文件I/O

    C和C 程序通常会对文件进行读写 并将此作为它们正常操作的一部分 不计其数的漏洞正是由这些程序与文件系统 其操作由底层操作系统定义 交互方式的不规则性而产生的 这些漏洞最常由文件的识别问题 特权管理不善 以及竞争条件导致 8 1 文件I O
  • 60行代码就能构建GPT!网友:比之前的教程都要清晰|附代码

    Pine 发自 凹非寺量子位 公众号 QbitAI 现在只用60行代码 就能从0构建GPT了 想当初 前特斯拉前AI总监的minGPT和nanoGPT也都还要300行代码 这个60行代码的GPT也有名字 博主将它命名为PicoGPT 不过和
  • Linux网络编程:Socket套接字编程(Server服务器 Client客户端)

    文章目录 一 定义和流程分析 1 定义 2 流程分析 3 网络字节序 二 相关函数 IP地址转换函数inet pton inet ntop 本地字节序 网络字节序 socket函数 创建一个套接字 bind函数 给socket绑定一个服务器