先自我介绍一下,小编浙江大学毕业,去过华为、字节跳动等大厂,目前阿里P7
深知大多数程序员,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年最新Linux运维全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上运维知识点,真正体系化!
由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新
如果你需要这些资料,可以添加V获取:vip1024b (备注运维)
正文
返回值:
成功
:实际接收的字节数
,失败
:-1
, 并设置errno
buffer
: 发送缓冲区首地址length
: 发送的字节数flags
: 接收方式(通常为0)MSG_DONTWAIT
: Enables nonblocking operation;非阻塞版本
MSG_OOB
:用于发送TCP类型的带外数据
(out-of-band)MSG_PEEK
:
接收消息的开头,但不删除该消息数据。 因此,随后的接收将
返回相同的数据
10、read()/write()
ssize\_t read(int fd, void \*buf, size\_t count);
ssize\_t write(int fd, const void \*buf, size\_t count);
- read()和write()经常会代替recv()和send()
- 通常情况下,看程序员的偏好
使用read()/write()和recv()/send()时最好统一
11、套接字的关闭
int close(int sockfd); //关闭双向通讯
int shutdown(int sockfd, int howto);
TCP连接
是双向的(是可读写的)
,当我们使用close
时,会把读写通道都关闭
,有时侯我们希望只关闭一个方向
,这个时候我们可以使用shutdown
。- 针对不同的howto,系统回采取不同的关闭方式。
howto = 0
关闭读通道,但是可以继续往套接字写数据。howto = 1
和上面相反,关闭写通道。只能从套接字读取数据。howto = 2
关闭读写通道,和close()一样
示例
客机向服务器写数据,服务器读数据并打印
net.h-包含的头文件以及宏定义
/\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
> File Name: net.h
> Author: xiuchengzhen
> CSDN: xiuchengzhen.blog.csdn.net
> Created Time: Tue 29 Mar 2022 05:45:13 AM PDT
\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*/
#ifndef NET\_H
#define NET\_H
#include<stdio.h>
#include<stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include<unistd.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include<errno.h>
#define SER\_PORT 5001 //端口号
#define SER\_ADDR "192.168.125.128" //ip地址
#define BUFSIZE 15 //发送数据的大小(字节)
#define USER\_QUIT "quit" (退出命令)
#endif
服务器sever.c:
/\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
> File Name: sever.c
> Author: xiuchengzhen
> CSDN: xiuchengzhen.blog.csdn.net
> Created Time: Tue 29 Mar 2022 01:41:36 AM PDT
\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*/
#include "net.h"
int main(int argc, const char \*argv[])
{
/\*\*\*\*\*\*\*\*socket文件创建\*\*\*\*\*\*\*\*\*\*\*/
int fd = socket( AF_INET, SOCK_STREAM, 0);
if(fd < 0)
{
perror("socket");
exit(-1);
}
/\*\*\*\*\*\*\*bind设置\*\*\*\*\*\*\*/
struct sockaddr\_in sin;
memset(&sin, 0, sizeof(sin)); //清零操作
sin.sin_family = AF_INET; //地址族
sin.sin_port = htons(SER_PORT);
#if 0
sin.sin_addr = inet\_addr(SER_ADDR);
#else
if(inet\_pton(AF_INET, SER_ADDR, (void \*)&sin.sin_addr) == 0)
{
perror("inet\_pton:");
exit(-1);
}
#endif
if(bind(fd, (struct sockaddr \*)&sin,sizeof(sin)) < 0)
{
perror("bind:");
exit(-1);
}
/\*\*\*\*\*\*\*\*listen\*\*\*\*\*\*\*\*\*/
if(listen(fd, 5) < 0)
{
perror("listen:");
exit(-1);
}
/\*\*\*\*\*\*\*accept阻塞接收\*\*\*\*\*\*\*\*\*/
int newfd;
if((newfd = accept(fd, NULL, NULL)) < 0)
{
perror("accept:");
exit(-1);
}
/\*\*\*\*\*\*read\*\*\*\*\*\*\*/
char buf[BUFSIZE];
int ret = -1;
while(1)
{
bzero((void \*)buf, BUFSIZE); //清零
do
{
ret = read(newfd, (void \*)buf, BUFSIZE-1);
}while(ret < 0 && EINTR == errno); //没读到就一直读
if(ret < 0) //读错误
{
perror("read");
exit(-1);
}
if(ret == 0) //连接断开
{
printf("client break link!\n");
break;
}
printf("re:%s\n", buf);
if(strncasecmp(buf, USER_QUIT, strlen(USER_QUIT)) == 0)
{
printf("client choice break link!\n");
break;
}
}
/\*\*\*\*\*\*\*\*\*关闭网络\*\*\*\*\*\*\*\*\*\*\*/
close(newfd);
close(fd);
return 0;
}
客机client.c:
/\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
> File Name: client.c
> Author: xiuchengzhen
> CSDN: xiuchengzhen.blog.csdn.net
> Created Time: Tue 29 Mar 2022 05:43:55 AM PDT
\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*/
#include "net.h"
int main(int argc, const char \*argv[])
{
/\*\*\*\*\*\*\*\*socket文件创建\*\*\*\*\*\*\*\*\*\*\*/
int fd = socket( AF_INET, SOCK_STREAM, 0);
if(fd < 0)
{
perror("socket");
exit(-1);
}
/\*\*\*\*\*\*\*connect设置\*\*\*\*\*\*\*/
struct sockaddr\_in sin;
memset(&sin, 0, sizeof(sin)); //清零操作
sin.sin_family = AF_INET;
sin.sin_port = htons(SER_PORT);
#if 0
sin.sin_addr = inet\_addr(SER_ADDR);
#else
if(inet\_pton(AF_INET, SER_ADDR, (void \*)&sin.sin_addr) == 0)
{
perror("inet\_pton:");
exit(-1);
}
#endif
if(connect(fd, (struct sockaddr \*)&sin,sizeof(sin)) < 0)
{
perror("connect:");
exit(-1);
}
printf("client connect success!\n");
char buf[BUFSIZE] = {0};
int ret = -1;
while(1)
{
bzero(buf, 0);
if(fgets(buf, BUFSIZE-1, stdin) == 0)
{
continue;
}
do
{
ret = write(fd, buf, strlen(buf));
}while(ret < 0 && EINTR == errno);
if (!strncasecmp (buf, USER_QUIT, strlen (USER_QUIT)))
{
printf ("Client is exiting!\n");
break;
}
}
return 0;
}
运行结果:
二、并发编程
主要是应对当多个客机对服务器进行连接的情况
。
- 当一个客机与服务器连接时,服务器创建一个线程或一个子进程为客机单独服务,主函数继续等待新的客机连接
1、多线程并发
实现过程在上面的例子上稍微改进
头文件net.h:
/\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
> File Name: net.h
> Author: xiuchengzhen
> CSDN: xiuchengzhen.blog.csdn.net
> Created Time: Tue 29 Mar 2022 05:45:13 AM PDT
\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*/
#ifndef NET\_H
#define NET\_H
#include<stdio.h>
#include<stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include<unistd.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include<errno.h>
#include <netinet/in.h>
#include<pthread.h>
#define SER\_PORT 5001
#define SER\_ADDR "192.168.125.128"
#define BUFSIZE 15
#define USER\_QUIT "quit"
#define BACK\_LOG 5
#endif
服务器sever.c:
/\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
> File Name: sever.c
> Author: xiuchengzhen
> CSDN: xiuchengzhen.blog.csdn.net
> Created Time: Tue 29 Mar 2022 01:41:36 AM PDT
\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*/
#include "net.h"
void \*client\_hander(void \*arg);
int main(int argc, const char \*argv[])
{
int i = 0;
/\*\*\*\*\*\*\*\*socket文件创建\*\*\*\*\*\*\*\*\*\*\*/
int fd = socket( AF_INET, SOCK_STREAM, 0);
if(fd < 0)
{
perror("socket");
exit(-1);
}
/\*\*\*\*\*\*\*bind设置\*\*\*\*\*\*\*/
struct sockaddr\_in sin;
memset(&sin, 0, sizeof(sin)); //清零操作
sin.sin_family = AF_INET;
sin.sin_port = htons(SER_PORT);
/\*\*\*\*\*\*\*\*\*\*\*优化1\*\*\*\*\*\*\*\*\*\*/
#if 1
sin.sin_addr.s_addr = htonl(INADDR_ANY); //当系统IP地址发生变化时,这里的地址也会随着变化
#else
if(inet\_pton(AF_INET, SER_ADDR, (void \*)&sin.sin_addr) == 0)
{
perror("inet\_pton:");
exit(-1);
}
#endif
if(bind(fd, (struct sockaddr \*)&sin,sizeof(sin)) < 0)
{
perror("bind:");
exit(-1);
}
/\*\*\*\*\*\*\*\*listen\*\*\*\*\*\*\*\*/
if(listen(fd, BACK_LOG) < 0) //设置为服务器模式,与最大接收数
{
perror("listen:");
exit(-1);
}
/\*\*\*\*\*\*\*\*\*多线程优化\*\*\*\*\*\*\*\*\*/
/\*\*\*\*\*\*\*accept阻塞接收\*\*\*\*\*\*\*\*\*/
while(1)
{
#if 0
int newfd;
if((newfd = accept(fd, NULL, NULL)) < 0)
{
perror("accept:");
exit(-1);
}
#else
int newfd[BACK_LOG];
struct sockaddr\_in cin;
char client_ip[16] = {0};
socklen\_t cin_len = (socklen\_t)sizeof(cin);
memset(&cin, 0, sizeof(cin));
if((newfd[i] = accept(fd, (struct sockaddr \*)&cin, &cin_len)) < 0) //阻塞接收
{
perror("accept:");
exit(-1);
}
if(inet\_ntop(AF_INET, (void \*)&cin.sin_addr, client_ip, sizeof(cin)) == NULL)
{
perror("inet\_ntop:");
exit(-1);
}
printf("client Port:%d,IP:%s\n",ntohs(cin.sin_port), client_ip);
#endif
pthread\_t tid;
if(pthread\_create(&tid, NULL, client_hander, (void \*)&newfd[i]) != 0)
{
printf("tid create error!\n");
exit(-1);
}
i++;
}
close(fd);
return 0;
}
void \*client\_hander(void \*newfd)
{
pthread\_detach(pthread\_self()); //设置线程分离属性,线程结束时自动回收
/\*\*\*\*\*\*read\*\*\*\*\*\*\*/
char buf[BUFSIZE];
int ret = -1;
while(1)
{
bzero((void \*)buf, BUFSIZE);
do
{
ret = read(\*(int \*)newfd, (void \*)buf, BUFSIZE-1);
}while(ret < 0 && EINTR == errno);
if(ret < 0)
{
perror("read");
exit(-1);
}
if(ret == 0)
{
printf("fd:%d client break link!\n", \*(int \*)newfd);
break;
}
printf("fd:%d read:%s\n", \*(int \*)newfd, buf);
if(strncasecmp(buf, USER_QUIT, strlen(USER_QUIT)) == 0)
{
printf("fd:%d client choice break link!\n", \*(int \*)newfd);
break;
}
}
/\*\*\*\*\*\*\*\*\*关闭网络\*\*\*\*\*\*\*\*\*\*\*/
close(\*(int \*)newfd);
return NULL;
}
客机client.c:
/\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
> File Name: client.c
> Author: xiuchengzhen
> CSDN: xiuchengzhen.blog.csdn.net
> Created Time: Tue 29 Mar 2022 05:43:55 AM PDT
\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*/
#include "net.h"
int main(int argc, const char \*argv[])
{
if(argc < 2)
{
printf("Please enter the port and address at run time!\n"); // ./运行文件 端口号 IP
printf("For example:\n ./ file port IP\n");
exit(-1);
}
/\*\*\*\*\*\*\*\*socket文件创建\*\*\*\*\*\*\*\*\*\*\*/
int fd = socket( AF_INET, SOCK_STREAM, 0);
if(fd < 0)
{
perror("socket");
exit(-1);
}
/\*\*\*\*\*\*\*connect设置\*\*\*\*\*\*\*/
struct sockaddr\_in sin;
int port = atoi(argv[1]);
if(port < 5000)
{
printf("The port number must be smaller than 5000\n");
exit(-1);
}
memset(&sin, 0, sizeof(sin)); //清零操作
sin.sin_family = AF_INET;
sin.sin_port = htons(port);
#if 0
sin.sin_addr = inet\_addr(argv[2]);
#else
if(inet\_pton(AF_INET, argv[2], (void \*)&sin.sin_addr) == 0)
{
perror("inet\_pton:");
exit(-1);
}
#endif
if(connect(fd, (struct sockaddr \*)&sin,sizeof(sin)) < 0)
{
perror("connect:");
exit(-1);
}
printf("client connect success!\n");
char buf[BUFSIZE] = {0};
int ret = -1;
while(1)
{
bzero(buf, 0);
if(fgets(buf, BUFSIZE-1, stdin) == 0)
{
continue;
}
do
{
ret = write(fd, buf, strlen(buf));
}while(ret < 0 && EINTR == errno);
if (!strncasecmp (buf, USER_QUIT, strlen (USER_QUIT)))
{
printf ("Client is exiting!\n");
break;
}
}
return 0;
}
运行结果:
2、多进程并发
只需在服务器上改动,其他不变:
/\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
> File Name: sever\_process.c
> Author: xiuchengzhen
> CSDN: xiuchengzhen.blog.csdn.net
> Created Time: Tue 29 Mar 2022 01:41:36 AM PDT
\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*/
#include "net.h"
void process\_hander(int log);
void client\_hander(int arg);
int main(int argc, const char \*argv[])
{
signal(SIGCHLD, process_hander);
/\*\*\*\*\*\*\*\*socket文件创建\*\*\*\*\*\*\*\*\*\*\*/
int fd = socket( AF_INET, SOCK_STREAM, 0);
if(fd < 0)
{
perror("socket");
exit(-1);
}
/\*\*\*\*\*\*\*bind设置\*\*\*\*\*\*\*/
struct sockaddr\_in sin;
memset(&sin, 0, sizeof(sin)); //清零操作
sin.sin_family = AF_INET;
sin.sin_port = htons(SER_PORT);
/\*\*\*\*\*\*\*\*\*\*\*优化1\*\*\*\*\*\*\*\*\*\*/
#if 1
sin.sin_addr.s_addr = htonl(INADDR_ANY); //当系统IP地址发生变化时,这里的地址也会随着变化
#else
if(inet\_pton(AF_INET, SER_ADDR, (void \*)&sin.sin_addr) == 0)
{
perror("inet\_pton:");
exit(-1);
}
#endif
if(bind(fd, (struct sockaddr \*)&sin,sizeof(sin)) < 0)
{
perror("bind:");
exit(-1);
}
/\*\*\*\*\*\*\*\*listen\*\*\*\*\*\*\*\*/
if(listen(fd, BACK_LOG) < 0) //设置为服务器模式,与最大接收数
{
perror("listen:");
exit(-1);
}
/\*\*\*\*\*\*\*\*\*多进程优化\*\*\*\*\*\*\*\*\*/
/\*\*\*\*\*\*\*accept阻塞接收\*\*\*\*\*\*\*\*\*/
while(1)
{
#if 0
int newfd;
if((newfd = accept(fd, NULL, NULL)) < 0)
{
perror("accept:");
exit(-1);
}
#else
int newfd;
struct sockaddr\_in cin;
char client_ip[16] = {0};
socklen\_t cin_len = (socklen\_t)sizeof(cin);
memset(&cin, 0, sizeof(cin));
if((newfd = accept(fd, (struct sockaddr \*)&cin, &cin_len)) < 0) //阻塞接收
{
perror("accept:");
**网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。**
**需要这份系统化的资料的朋友,可以添加V获取:vip1024b (备注运维)**
![img](https://img-blog.csdnimg.cn/img_convert/2b03b4a99ce4b10c551157489396f343.jpeg)
**一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!**
\*\*\*\*\*\*accept阻塞接收\*\*\*\*\*\*\*\*\*/
while(1)
{
#if 0
int newfd;
if((newfd = accept(fd, NULL, NULL)) < 0)
{
perror("accept:");
exit(-1);
}
#else
int newfd;
struct sockaddr\_in cin;
char client_ip[16] = {0};
socklen\_t cin_len = (socklen\_t)sizeof(cin);
memset(&cin, 0, sizeof(cin));
if((newfd = accept(fd, (struct sockaddr \*)&cin, &cin_len)) < 0) //阻塞接收
{
perror("accept:");
**网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。**
**需要这份系统化的资料的朋友,可以添加V获取:vip1024b (备注运维)**
[外链图片转存中...(img-JNPPpdFy-1713460293532)]
**一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!**