网络编程

目录
系统编程

系统编程
1st
1、Sys:
系统就是(linux =>kernel)给用户土工一些接口(function),用户通过这些接口编程及时系统编程

2、kernel:
1、文件系统:把硬盘抽象成文件系统,方便用户使用
Windows:ms_dos fat16 fat32 fat64 ntfs ……
Linux: fat nfs sxt2 ext3 ext4……
2、内存管理:
虚拟内存:
32位系统下(4G)
0 —— 3G : 用户态
stsck : 局部变量 临时变量 模块变量
heap : 动态内存 malloc calloc realloc
DS : 全局变量和静态变量
BSS : 未初始化
Ro : 初始化
Const : 常量
Code : 代码
3 —— 4G : 系统态
物理内存:内存条

	Cpu : 如何找到虚拟内存地址 => 物理地址 => 系统启动的时候完成编址 => 内存管理机制  页表储存机制

	独立编址:
	统一编址:
	冯诺依曼体系结构:
	哈佛体系结构:

3 进程管理:
	就是一段可执行代码,并放在内存中运行就是进程
	进程唯一标识就是进程号

	init进程:1号进程,是因为1号进程是所有进程祖先。
	所有的进程都是通过1号进化直接或者间接创建的。
	1号进程杀不死

	进程状态:
	D    Uninterruptible sleep (usually IO)  不可中端睡眠状态
	R    Running or runnable (on run queue) 运行或者可运行状态
	S    Interruptible sleep (waiting for an event to complete)
		表示可中端睡眠状态
	T    Stopped, either by a job control signal or because it is
	     being traced.
		 表示停止或者可在追踪状态
		 W    paging (not valid since the 2.6.xx kernel)
			表示保存在页中
		 X    dead (should never be seen)
		 	表示快要退出状态
		 Z    Defunct ("zombie") process, terminated but not reaped by
		      its parent.
			 表示僵尸进程
	<    high-priority (not nice to other users)
		表示高优先级
	N    low-priority (nice to other users)
		表示底优先级
	L    has pages locked into memory (for real-time and custom IO)
		表示锁在在内存中
	s    is a session leader
		表示会话领导者
	l    is multi-threaded (using CLONE_THREAD, like NPTL
	     pthreads do)
		 表示多线程
	+    is in the foreground process group
		表示进程组
	
	内核版本号:
		[root@localhost 1st]# uname -r
		2.6.18-194.el5

		2 :表示主版本号
			表示系统架构发生重大改变才会升级
		6 :表示次版本号
			表示GNU核心工程师才可以修改
			奇数:表示测试版本
			偶数:表示稳定版本
		18:表示释放版本号
			表示一些系统bug修改
	进程五态模型:
		新建态:创建进程所需要资源表相 : 进程表相, 打开文件描述符,建立空间地址,分配内存资源 ....
		就绪态:等待CPU分配运行资源
		运行态:获得CPU资源,并放在内存中运行
		挂起态:也叫阻塞态,就是一个IO请求或者中断等到程序处于挂起状态。
		终止态:回收进程资源。

	(面试)进程的五态模型:  
		新建态 : 创建进程所需要的资源表象 : 进程表象,打开文件描述符,建立空间地址,分配内存资源……
		就绪态: 等待cpu分配运行资源
		运行态: 获得cpu资源,并放到内存中运行
		挂起态:也叫阻塞态,就是一个IO请求或者中断等到程序处于挂起状态
		终止态:回收进程资源

	进程之间通讯(方法):
		1信号:软中断
		2管道:半双工模式,必须确保双方都在线
			三种通讯模式:
				单工模式:一端只能写或读
				半双工: 一端只能读, 一端只能写
				全双工: 一端能读能写

			匿名管道:
				只能实现父子进程或兄弟进程之间的通讯
			有名管道:
				可以实现任何进程之间的通讯

		3消息队列:可以确保双方不在线的问题
		4共享内存:
		5信号量:锁(要避免死锁)
		6套接子 => net 利用套接子编程就是网络编程
			TCP: 三次握手机制试实现原理(面试必问)
			UDP:

4、设备驱动
5、网络

在linux下的操作文件的两种方式
文件指针: fileIO
文件描述符:sysIO
fileIO sysIO
标准输入:键盘 鼠标 stdent 0
标准输出:显示器 打印机 stdout 1
错误输出:显示器 打印机 stderr 2
sysIO:
打开
Int open (const char * pathname, int flats)
第一个参数:表示文件路径
第二个参数:表示标志位
O_RDONLY 只读 r O_RDONLY
O_WRONLY 只写 r+ O_RDWR
O_RDWR 读写方式 w O_WRONLY | O_CREAT | O_TRUNC
O_CREAT 创建文件 w+ O_RDWR | O_CREAT | O_TRUNC
O_EXCT 检查文件是否存在 a O_WRONLY | O_APPEND | O_CREAT
O_APPEND 在读或写时 写入文件已追加的方式写入 a+ O_RDWR | O_APPEND | O_CREAT
O_TRUNC 清空
返回值:
成功:返回一个没使用过的新的最小文件描述符
失败:-1
文件描述符就是一个非负的整数,一个进程最多能打开1024个描述符

	Int open (const char * pathname, int flats,mode_t mode)
		参数三: 表示模式(创建文件的权限)

	Int creat (const char * pathname, mode_t mode)

关闭:
	Int close(int fd)

size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
参数一:是读取的数据存放的内存的指针(可以是数组,也可以是新开辟的空间,ptr就是一个索引)
参数二:是每次读取的字节数
参数三:是读取的次数
参数四::是要读取的文件指针
读文件:
Ssize_t read(int fd, void *buf, size_t count) //无缓冲区 fread有缓冲区
参数一:文件描述符
参数二:和获取数据的空间地址
参数三:空间大小
返回值:
成功:获取数据个数 字节
失败:-1
文件结尾:0

写文件:
		Ssize_t write(int fd, const void *buf, ssize_t count)			//无缓冲区 		fwrite有缓冲区

fwrite函数原型:
size_t fwrite(const void* buffer,size_t size, size_t count, FILE* stream);
功能:
向文件中写入一个数据块。(写入的数据不限于文本格式,也可以是二进制文件等)
返回值:返回实际写入的数据块数。
参数:

  1. buffer是一个指针。对fwrite来说是要写入数据的地址。
  2. size是要写入内容的单字节数。
  3. count是要进行写入size字节的数据项的个数。
  4. stream为目标文件指针
    5)返回实际写入的数据项个数count。
    sprintf是个变参函数,定义如下:
    int sprintf( char *buffer, const char *format [,argument] … );
    除了前两个参数类型固定外,后面可以接任意多个参数。而它的精华,显然就在第二个参数:格式化字符串上。

2nd
判断文件权限:
【判断文件是否存在】
Int access(const char *pathname ,int mode)
参数二:模式
R_OK: 读
W_OK: 写
X_OK: 执行
F_OK: 判断文件是否存在
返回值:
成功:0
失败:-1

ssize_t read(int fd, void *buf, size_t count);
事件文件结构体
struct input_event {
struct timeval time;//按键的时间
__u16 type;//事件类型
__u16 code;//事件 模拟成什么按键
__s32 value;//按下1和抬起0
};

=================
dup
A => hello => open => write
B => world => open => write
复制文件描述符
int dup(int oldfd);
返回值,
未使用最小文件描述符
int dup2(int oldfd, int newfd);
第一个参数:旧的 fd1
第二个参数:新的 fd2 => 8
注意:可以指定一个未使用文件描述符
指定一个被占用的文件描述符,则关闭新的文件描述符,然后指向旧的文件描述符。

off_t lseek(int fildes, off_t offset, int whence);
第一个参数:表示文件描述符
第二个参数:表示偏移大小
第三个参数:表示偏移位置

返回值:
	成功:表示偏移大小(从文件开头)
	失败:-1

练习:
循环实现一个文件播放

获取文件状态标志
int fcntl(int fd, int cmd);
int fcntl(int fd, int cmd, long arg);
int fcntl(int fd, int cmd, struct flock *lock);
第一个参数:表示文件描述符
第二个参数:表示命令
F_DUPFD : 表示复制文件描述符 能实现dup2的功能,但要手动关闭已占用的文件描述符
F_GETFL : 表示获取状态标志
F_SETFL : 表示设置状态标志
第三个参数:表示对命令补充
返回值:
失败:-1

获取文件属性
int stat(const char *path, struct stat *buf);
int fstat(int filedes, struct stat *buf);
int lstat(const char *path, struct stat *buf);

第一个参数:表示文件路径
第二个参数:表示文件状态结构体
struct stat {
	dev_t     st_dev;     /* ID of device containing file */
	//表示设备id
	ino_t     st_ino;     /* inode number */
	表示文件inode节点 
	mode_t(int)    st_mode;    /* protection */
	表示文件类型和权限
	nlink_t   st_nlink;   /* number of hard links */
	表示硬链接
	uid_t     st_uid;     /* user ID of owner */
	表示属主
	gid_t     st_gid;     /* group ID of owner */
	表示属组
	dev_t     st_rdev;    /* device ID (if special file) */
	表示设备id 块设备和字符设备
	off_t     st_size;    /* total size, in bytes */
	表示文件大小
	blksize_t st_blksize; /* blocksize for filesystem I/O */
	表示块大小
	blkcnt_t  st_blocks;  /* number of blocks allocated */
	表示多少块
	time_t    st_atime;   /* time of last access */
	表示访问时间 秒数 1970年1月1日 => 访问文件秒数
	time_t    st_mtime;   /* time of last modification */
	表示修改文件内容时间
	time_t    st_ctime;   /* time of last status change */
	表示修改文件属性(权限 属主 属组)
};
返回值:
	成功:0
	失败:-1
[root@localhost 2nd]# stat 01_cp.c 
  File: “01_cp.c”
    Size: 637             Blocks: 8          IO Block: 4096   一般文件
	Device: 802h/2050d      Inode: 8592756     Links: 1
	Access: (0644/-rw-r--r--)  Uid: (    0/    root)   Gid: (    0/    root)
	Access: 2019-12-02 15:51:28.000000000 +0800
	Modify: 2019-12-02 09:26:13.000000000 +0800
	Change: 2019-12-02 09:26:13.000000000 +0800

[root@localhost 2nd]# ll
总计 64
-rw-r--r-- 1 root root  637 12-02 09:26 01_cp.c
-rw-r--r-- 1 root root  329 12-02 09:32 02_mode.c
第一列:表示文件类型和权限
	文件类型:第一列第一个字符
		- : 表示普通文件
		d : 表示目录文件
		c : 表示字符设备类文件
		l : 表示软连接文件
		b : 表示块设备类文件
		s : 表示套接子文件
		p : 表示管道文件
	文件权限:
		r : 表示只读
		w : 表示只写
		x : 表示可执行
		- : 表示无权限

		三位为一组,工三组
		第一组 : 表示属主权限 文件拥有者
		第二组 : 表示属组权限 文件拥有组
		第三组 : 表示其他用户权限
第二列:表示硬连接数
	硬链接:相当于给文件做一个备份
		ln srcfilename destfilename
	软连接:想给给文件做一个快捷方式
		ln -s srcfilename destfilename
第三列:表示属主
	uid => username
	/etc/passwd : 用户帐号信息文件

第四列:表示文件属组
	gid -> groupname
	/etc/group
第五列:表示文件大小 字节
	
第六列:表示文件内容时间

	atime : 表示访问时间 cat tail head more less ...
	mtime : 表示修改内容时间 同时会触发atime ctime
	ctime : 表示修改属性时间(权限 属主 属组)
第七列:表示文件名

实现 ll filename

3rd
man 2 => sys
man 3 => c
open => option => close
fd => read write lseek dup dup2 fcntl
stat => type mode link uid gid size name …

/etc/passwd
[root@localhost include]# head -n 3 /etc/passwd
root❌0:0:this is root username:/root:/bin/bash
bin❌1:1:bin:/bin:/sbin/nologin
daemon❌2:2:daemon:/sbin:/sbin/nologin
第一列:表示用户名
第二列:表示密码 /etc/shadow => md5
第三列:表示用户uid(int) adduser useradd
第四列:表示用户组gid groupadd
第五列:表示描述行信息
第六列:表示用户家目录
root => /root
otheruser => /home/username
第七列:表示用户所使用shell

通过用户uid返回用户信息结构体
struct passwd *getpwuid(uid_t uid);
struct passwd {
char pw_name; / user name */
char pw_passwd; / user password /
uid_t pw_uid; /
user ID /
gid_t pw_gid; /
group ID */
char pw_gecos; / real name */
char pw_dir; / home directory */
char pw_shell; / shell program */
};

通过用户名获取用户帐号信息文件
truct passwd *getpwnam(const char *name);
循环获取用户帐号信息文件
struct passwd *getpwent(void);
void setpwent(void);//设置到文件开头
void endpwent(void);//结束销毁

用户组信息文件
/etc/group
[root@localhost 3rd]# head -n 3 /etc/group
root❌0:root
bin❌1:root,bin,daemon
daemon❌2:root,bin,daemon
第一列:表示组名
第二列:表示组密码 //etc/gshadow
第三列:表示组gid
第四列:表示组成员

struct group *getgrgid(gid_t gid);
struct group *getgrnam(const char *name);
struct group {
char gr_name; / group name */
char gr_passwd; / group password /
gid_t gr_gid; /
group ID */
char *gr_mem; / group members */

"tom jim mary" ... char *
"tom" "jim" "mary" ... char *p[]

};
struct group *getgrent(void);
void setgrent(void);
void endgrent(void);

[root@localhost 3rd]# grub-md5-crypt
Password: 明文
Retype password:
$1 3 w 9 x g 0 3w9xg0 3w9xg0lsmyAbWNyEtWqVk.qcbys1 暗文
$1 3 w 9 x g 0 3w9xg0 3w9xg0 :密钥
lsmyAbWNyEtWqVk.qcbys1 :密码
md5算法加密函数
char *crypt(const char *key, const char *salt);
第一个参数:表示关键字(明文)
第二个参数:表示密钥
返回值:
就是暗文

注意:
	1 链接密码库 -lcrypt
	2 指定宏命令,且报存在头文件前面

/etc/shadow 用户密码帐号信息文件
[root@localhost 3rd]# head -n 3 /etc/shadow
root: 1 1 1Kc81kkrT$SLMBf6Xwo4eK2R0WSGMXu0:18233:0:99999:7:::
bin::17678:0:99999:7:::
daemon:
:17678:0:99999:7:::
第一列:表示用户名
第二列:表示密码
第三列:表示从1970年1月1日到上次间隔天数
第四列:表示两次修改密码间隔天数
0 : 表示随时可以修改
第五列:表示密码有效期
第六列:表示密码失效前天数
第七列:表示密码失效后还可以使用天数
第八列:表示帐号失效天数
第九列:表示保留

通过用户名获取密码信息结构体
struct spwd *getspnam(char *name);
struct spwd {
	char          *sp_namp; /* user login name */
	char          *sp_pwdp; /* encrypted password */
	long int      sp_lstchg; /* last password change */
	long int      sp_min; /* days until change allowed. */
	long int      sp_max; /* days before change required */
	long int      sp_warn; /* days warning for expiration */
	long int      sp_inact; /* days before account inactive */
	long int      sp_expire; /* date when account expires */
	unsigned long int  sp_flag; /* reserved for future use */
}
struct spwd *getspent();
void setspent();
void endspent();

====================================
时间函数
time_t time(time_t *t); //time_t(int)
参数:表示时间变量
返回值:
成功:1970年1月1日 => now => seconds
把时间秒数转换成字符串
char *ctime(const time_t *timep);
把时间秒数转换成时间结构体

获取国际标准时间
struct tm *gmtime(const time_t *timep);
struct tm {
	int tm_sec;         /* seconds */
	int tm_min;         /* minutes */
	int tm_hour;        /* hours */
	int tm_mday;        /* day of the month */
	int tm_mon;         /* month */
	int tm_year;        /* year */
	int tm_wday;        /* day of the week */
	int tm_yday;        /* day in the year */
	int tm_isdst;       /* daylight saving time */
};

获取本地时间
struct tm *localtime(const time_t *timep);

把时间结构体转换字符串
char *asctime(const struct tm *tm);
把时间结构体转换成秒
time_t mktime(struct tm *tm);

时间格式化函数
size_t strftime(char *s, size_t max, const char *format,
                           const struct tm *tm);
第一个参数:表示保存时间格式空间
第二个参数:表示空间大小
第三个参数:表示就是时间格式
	年:	%Y %y
	月:	%m
	日:	%d
	小时:	%H
	分钟:	%M
	秒:	%S
	星期:	%w
第四个参数:表示时间结构体

查找链接文件目标文件
ssize_t readlink(const char *path, char *buf, size_t
bufsiz);

第一个参数:表示文件路径
第二个参数:表示保存目标文件空间
第三个参数:表示空间大小
返回值:

=================================================
修改文件权限
int chmod(const char *path, mode_t mode);
int fchmod(int fildes, mode_t mode);
修改文件属主和属组
int chown(const char *path, uid_t owner, gid_t group);
int fchown(int fd, uid_t owner, gid_t group);
int lchown(const char *path, uid_t owner, gid_t group);
创建硬链接
int link(const char *oldpath, const char *newpath);
创建软链接
int symlink(const char *oldpath, const char *newpath);
创建文件
int open(const char *pathname, int flags);
int open(const char *pathname, int flags, mode_t mode)
int creat(const char *pathname, mode_t mode);
删除文件
int unlink(const char *pathname);
创建目录
int mkdir(const char *pathname, mode_t mode);
删除目录
int rmdir(const char *pathname);
int remove(const char *pathname);
切换目录
int chdir(const char *path);
int fchdir(int fd);
获取当前工作目录
char *getcwd(char *buf, size_t size);
char *get_current_dir_name(void);
char *getwd(char *buf);

4th
修改文件权限
int chmod(const char *path, mode_t mode);
int fchmod(int fildes, mode_t mode);
默认权限
mode_t umask(mode_t mask);

高级权限:
属主:u
属组:g
其他用户:o
所有用户:a
表示属主特权
S_ISUID 0004000 set UID bit
chmod 04XXX filename
chmod u+s filename
目录:对目录不适用
文件:二进制可执行文件,如果是管理员的命令,而普通用户需要执行,则可以设置这样一个特权。则普通用户执行这个命令就会委托管理员去执行。
S_ISGID 0002000 set-group-ID bit (see below)
chmod 02XXX filename | dirname
chmod g+s filename | dirname
目录:所有用户在目录中创建文件或者目录都归目录的属组所有
文件:对文件不适用
S_ISVTX 0001000 sticky bit (see below)
chmod 01XXX filename | dirname
chmod o+t filename | dirname
目录:如果设置特权,则每一个用户只能查看别用户文件,不可以修改或者删除。
文件:不适用

打开目录
DIR *opendir(const char *name);
关闭目录
int closedir(DIR *dir);
读文件目录信息
int readdir(unsigned int fd, struct dirent *dirp,
unsigned int count); => open
struct dirent *readdir(DIR dir);
struct dirent {
ino_t d_ino; /
inode number /
off_t d_off; /
offset to the next dirent /
unsigned short d_reclen; /
length of this record /
unsigned char d_type; /
type of file /
char d_name[256]; /
filename */
};

enum
{
DT_UNKNOWN = 0,

define DT_UNKNOWN DT_UNKNOWN

DT_FIFO = 1,		表示管道 p

define DT_FIFO DT_FIFO

DT_CHR = 2,			表示字符设备

define DT_CHR DT_CHR

DT_DIR = 4,			表示目录

define DT_DIR DT_DIR

DT_BLK = 6,			表示块设备

define DT_BLK DT_BLK

DT_REG = 8,			表示普通文件

define DT_REG DT_REG

DT_LNK = 10,		表示链接文件

define DT_LNK DT_LNK

DT_SOCK = 12,		表示套接子

define DT_SOCK DT_SOCK

DT_WHT = 14

define DT_WHT DT_WHT

进程:
就是一段可执行程序,放在内存中运行
唯一标识就是进程号(pid)
进程号由系统来决定
子进程是由父进程(ppid)而来的,父进程代表的是终端
子进程复制父进程的所有资源(进程表相,文件描述符,工作目录,默认权限,内存空间………)
子进程没有脱离父进程的话,子进程受父进程影响

进程是系统资源管路的最小单位
线程是进程执行流的最小单位

线程是在进程的基础之上提出的,先有进程,才有线程

特性:
	动态性:动态产生,动态消亡过程
	独享性:进程间的内存空间是独享的
	并发性:谁先获得cpu资源谁先运行,竞争cpu资源
	异步性:cpu在同一时间段只能运行一段代码
		通过时间片轮转机制实现的	cpu只有一个

进程五态模型
新建态 就绪态 运行态 阻塞态 终止态
新建态:创建进程所需要资源表相 : 进程表相, 打开文件描述符,建立空间地址,分配内存资源 …
就绪态:等待CPU分配运行资源
运行态:获得CPU资源,并放在内存中运行
挂起态:也叫阻塞态,就是一个IO请求或者中断等到程序处于挂起状态。
终止态:回收进程资源。

进程间的通讯
信号 管道 信号队列 共享内存 信号量 套接子
1信号:软中断
2管道:半双工模式,必须确保双方都在线

			匿名管道(piep()):
				只能实现父子进程或兄弟进程之间的通讯
			有名管道(mkfifo()):
				可以实现任何进程之间的通讯

		3消息队列:可以确保双方不在线的问题
		4共享内存:
		5信号量:锁(要避免死锁)
		6套接子 => net 利用套接子编程就是网络编程
			TCP: 三次握手机制试实现原理(面试必问)
			UDP:

获取进程号:
pid_getpid(void);
获取父进程号:
pid_getppid(void);
创建子进程
pid_t fork(void)
返回值:
-1 : 失败
0 : 子进程运行
1: 父进程运行
//运行时段变量:运行起来才起作用

进程退出
正常退出
从main函数中退出 return
调用exit
调用_exit() or _EXIT()
调用字后一个线程退出 pthread_exit
调用最后一个线程返回return exit _exit

异常退出
调用abort
void abort(void)
调用一个信号 信号一般都得是终止或者中断
int kill(pid_t uid,int sig)
参数一是用户名
参数二是信号
1) SIGHUP 2) SIGINT 3) SIGQUIT 4) SIGILL 5) SIGTRAP
6) SIGABRT 7) SIGBUS 8) SIGFPE 9) SIGKILL 10) SIGUSR1
11) SIGSEGV 12) SIGUSR2 13) SIGPIPE 14) SIGALRM 15) SIGTERM
16) SIGSTKFLT 17) SIGCHLD 18) SIGCONT 19) SIGSTOP 20) SIGTSTP
21) SIGTTIN 22) SIGTTOU 23) SIGURG 24) SIGXCPU 25) SIGXFSZ
26) SIGVTALRM 27) SIGPROF 28) SIGWINCH 29) SIGIO 30) SIGPWR
31) SIGSYS 34) SIGRTMIN 35) SIGRTMIN+1 36) SIGRTMIN+2 37) SIGRTMIN+3
38) SIGRTMIN+4 39) SIGRTMIN+5 40) SIGRTMIN+6 41) SIGRTMIN+7 42) SIGRTMIN+8
43) SIGRTMIN+9 44) SIGRTMIN+10 45) SIGRTMIN+11 46) SIGRTMIN+12 47) SIGRTMIN+13
48) SIGRTMIN+14 49) SIGRTMIN+15 50) SIGRTMAX-14 51) SIGRTMAX-13 52) SIGRTMAX-12
53) SIGRTMAX-11 54) SIGRTMAX-10 55) SIGRTMAX-9 56) SIGRTMAX-8 57) SIGRTMAX-7
58) SIGRTMAX-6 59) SIGRTMAX-5 60) SIGRTMAX-4 61) SIGRTMAX-3 62) SIGRTMAX-2
63) SIGRTMAX-1 64) SIGRTMAX
头文件#include <signal.h>

return 和 exit 的区别
return是关键字 exit是一个函数
return是语言级别 exit是系统级别
return退出时吧控制权交给调动函数 exit退出是吧控制权交给系统

exit和_exit的区别:
exit会刷新缓冲区,释放文件描述符,释放空间 ……
exit会调用atexit函数
int atexit(void (*function)(void));
注册顺序跟销毁顺序相反

父进程等待子进程状态
pid_t wait(int *status);
参数:表示等待子进程状态标志
返回值:
成功:
子进程的pid
失败:
-1
宏:
WIFEXITED(status)为真时,为正常退出 正常退出 为1 异常为0
WEXITSTATUS(status)表示获取正常退出时的返回值 0~255

	WIFSIGNALED(status)表示异常退出	异常退出值为1	正常为 0
	WTERMSIG(status)表示返回信号值

pid_t waitpid(pid_t pid, int *status, int options);

5th
//同一个父进程创建多个子进程,如果出现父进程结束了,多的子进程会被一号进程收养
进程环境:
文件中设置进程的环境变量只对文件内有效,外围无效

pid_t wait(int *status);
参数:表示等待子进程状态
表示正常退出:
WIFEXITED(status) 如果这个宏为真,则表示正常退出
WEXITSTATUS(status) 表示获取正常退出返回值,返回值范围0~255

表示异常退出
WIFSIGNALED(status) : 表示异常退出 则为真
WTERMSIG(status) : 表示返回信号值

求素数 3000 ~ 6000
练习:
创建10个进程

==============================
进程环境
extern char **environ;
案例:
HOSTNAME=localhost.localdomain

获取环境变量
char *getenv(const char *name);
参数:表示变量名

修改环境变量
int setenv(const char *name, const char *value, int overwrite);
第一个参数:表示变量名
第二个参数:表示变量值
第三个参数:表示是否修改
1 : 表示修改
0 : 表示不修改
返回值:
成功0
失败-1

注意:如果是一个不存在的环境变量,设置这个环境变量,则会不会设置成功

int putenv(char *string);
	string => name=value

删除环境变量
int unsetenv(const char *name);

清空所有的环境变量
int clearenv(void);

==========================
exec家族函数 执行外部命令函数
int execl(const char *path, const char *arg, …);
第一个参数:表示命令路径 必须是绝对路径
第二个参数:表示执行命令
… : 表示对命令补充
返回值:
失败:-1
int execlp(const char *file, const char *arg, …);
第一个参数:表示文件路径 即可以是绝对路径,也可以是相对路径
int execle(const char *path, const char *arg,
…, char * const envp[]);

第一个参数:表示命令路径 必须是绝对路径
第二个参数:表示执行命令
...		  : 表示对命令补充
后面的参数:表示环境变量

int execv(const char *path, char *const argv[]);
第一个参数:表示命令路径
第二个参数:表示命令和参数
int execvp(const char *file, char *const argv[]);
int execve(const char *filename, char *const argv[],
                  char *const envp[]);

第一个参数:命令路径 必须是绝对路径
第二个参数:表示传递参数
第三个参数:表示环境变量

==========================
孤儿进程:
父进程创建一个子进程, 而父进程退出而子进程还处于运行状态,则这个子进程就变成孤儿进程。
孤儿进程就会被1号进程收养。

僵尸进程:
父进程创建一个子进程,子进程退出而父进化一直处于运行状态
守护进程:
一直运行在系统后台,用于监听用户输入指令,监听到这些指令作出相应的操作。
1 创建孤儿进程
2
受原控制终端影响
受原进程组影响
获取进程组id
pid_t getpgrp(void);
pid_t getpgid(pid_t pid);
受原会话影响
获取会话id
pid_t getsid(pid_t pid);

	创建一个新的会话
	pid_t setsid(void);

3 修改当前工作目录
4 修改umask值
5 关闭文件描述符
6 接受信号处理

创建守护进化
int daemon(int nochdir, int noclose);

获取资源限额
int getrlimit(int resource, struct rlimit rlim);
第一个参数:表示资源
RLIMIT_NOFILE :表示获取文件描述符资源
RLIMIT_STACK :表示堆栈大小
12M => 4G => 3G
第二个参数:表示资源结构体
struct rlimit {
表示软资源限额
rlim_t rlim_cur; /
Soft limit /
表示硬资源限额
rlim_t rlim_max; /
Hard limit (ceiling for rlim_cur) */
};
返回值:
成功0
失败-1
设置资源限额
int setrlimit(int resource, const struct rlimit *rlim);

==================
创建进程vfork
pid_t vfork(void);
1 确保子进程先运行,父进程后运行
2 vfork创建进化空间共享
fork创建进化空间是独享
3 vfork()子进程不可以用return退出,会导致段错误

6th
指针数组:
int *p[ ] 是一个数组 元素为指针的数组 记法:先指针再数组 谁在后就是什么 前面是附属关系(元素)
数组指针:
int (*p)[ ] 是一个指针,指向数组的指针 记法:先数组再指针 谁在后就是什么(指针) 前面是指向的东西
进程环境:
extern char **environ;
int main(int argc, char **argv, char **env)

char *argv[] => "zhangsan"

================================
信号:软中断机制

信号源:kill -l
	ctrl + c : SIGINT
	ctrl + \ : SIGQUIT
	abort	 : SIGABRT
	kill 	 : SIGKILL
	pipe	 : SIGPIPE
	alarm	 : SIGALRM

发送任意信号
	int kill(pid_t pid, int sig);
	第一个参数:表示进程号
	第二个参数:表示信号源
	返回值:
		成功 :0
		失败 : -1
接受信号
	sighandler_t signal(int signum, sighandler_t handler);
	第一个参数:表示信号源
	第二个参数:表示接受到信号处理方式
		SIG_IGN : 表示忽略
		SIG_DFL : 表示默认 中断
		func	:  表示自定义
		typedef void (*sighandler_t)(int);
	返回值:
		成功:指向前一个信号函数
		失败:SIG_ERR


发送闹钟信信号
	unsigned int alarm(unsigned int seconds);

接受信号返回
	int pause(void);

定时器:
获取定时器时间结构体
int getitimer(int which, struct itimerval *value);
设置定时器
int setitimer(int which, const struct itimerval *value,
		struct itimerval *ovalue);
第一个参数:表示定时器类型
	ITIMER_REAL : 表示机器时间
		SIGALRM => 14
	ITIMER_VIRTUAL : 表示用户态所消耗时间
		SIGVTALRM => 26
	ITIMER_PROF : 表示用户态和系统态所消耗时间
		SIGPROF => 27

第二个参数:表示时间结构体
	设定闹钟时间案例
	struct itimerval {
		表示循环时间
		struct timeval it_interval; /* next value */
		表示第一次执行时间
		struct timeval it_value;    /* current value */
	};
	struct timeval {
		表示秒
		long tv_sec;                /* seconds */
		表示微妙
		long tv_usec;               /* microseconds */
	};

第三个参数:表示上次设定闹钟时间结构体 NULL
返回值:
	成功 0
	失败 -1

=====================================
管道命令:|
通过|把所有的命令连接起来,而前一个命令输出作为后一个命令输入
[root@localhost sig]# cat /etc/passwd | cut -d : -f 7 | sort | uniq | grep -v ^$ | wc -l

cat : 查看文件内容
cut : 表示切割
sort : 排序
uniq : 去掉重复行
grep : 查找匹配信息
wc : 统计
	-l : 表示行
	-w : 表示单词
	-c : 表示字符

管道文件:
创建管道文件
mkfifo filename

管道:进程之间通讯
数据通讯模式三种:
单工模式:一端只能写或读
半双工: 一端只能读, 一端只能写
全双工: 一端能读能写

匿名管道:只能进行父子进化或者兄弟进程之间通讯
创建匿名管道
int pipe(int filedes[2]);

		fd[0] => read
		fd[1] => write
	
	匿名管道大小64K

有名管道:任意进程之间的通讯
	创建管道文件
		int mkfifo(const char *pathname, mode_t mode);
			第一个参数:表示文件名
			第二个参数:表示文件模式

int unlink(const char *pathname);
关闭或删除管道文件
Unlink

练习:
实现 cat /etc/passwd | grep root

int fp => buf => fd[1] => read => fd[0] => strstr


child
exec函数家族  => stdout => 1 fd[1] dup2

parent => stdin => 0 fd[0] dup2 => stdout

有名管道:实现任意进程之间通讯

===========================
homework :
1 : 封装定时器
1 => 1111 => 1
2 => 2222 => 0
4 => 4444 => 1
7 => 7777 => 1
8 => 8888 => 0

	struct timer_t{
		struct timer_t *prev;
		struct timer_t *next;
		int t;//表示定时器时间
		int count;//表示时间累加器
		void *data;//表示指定数据
		void (*func)(void *data);//执行函数
		int flag;//是否循环
			//1 表示循环 0 表示不循环
		....	
	};

2 : 实现一对一聊天 VT 

================================================
7th
exit :会自动调用退出函数
_exit:有缓冲区

文件描述符 :fd

1:获取关键字
2:创建共享内存
3:映射共享内存到进程中
4:写入数据到空间地址中
5:读数据

shmid :创建共享内存
ipcs -m:查看共享内存

删除
ipcrm -m shmid
ipcrm -M key

映射内核态空间到进程的空间地址中
shmat
1:共享内存地址id
2:映射空间地址
3:标示位0

成功:返回
失败:返回NULL

内存空间重叠尽量使用memmove

RM销毁

8th
管道要确保双方都在线、

消息队列
发送端:只负责发送,无论对方是否在线都可以发送
接收端:只负责接收
1获取创建消息队列关键字
Key_t ftok(const char *pathname,int proj_id)
第一个参数:表示文件路径 inode
第二个参数:表示用户输入序列号
返回值:
一般情况下,是把序列号转换16进制并保存到我关键字高位(8位),把文件inode节点转换
成16进制作为关键字低位(16位)组成起来作为关键字
2、创建消息队列
Int msgget(key_t key,int msgflg);
第一个参数:表示消息队列关键字
第二个参数:表示创建消息队列标示位
IPC_CREAT:表示创建
IPC_EXCL:表示判断消息队列是否存在,必须跟IPC_CREAT同时使用
返回值:
成功:表示消息队列id
失败: -1
查看消息队列
Ipcs -q
删除消息队列
Ipcrm -q msgid
Ipcrm Q key
3、发送消息
Int msgsnd(int msqid,const void *msgp,size_t msgsz,int msgflg);
第一个参数:表示消息队列id
第二个参数:表示发送数据空间地址
第三个参数:表示数据大小
第四个参数:表示标志位 0
返回值:
成功:0
失败:-1

4 接受数据
	ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long
	       msgtyp, int msgflg);
	第一个参数:表示消息队列id
	第二个参数:表示保存数据空间地址
	第三个参数:表示空间大小
	第四个参数:表示数据类型,如果不考虑数据类型 0
	第五个参数:表示标志位 0
	返回值:
		成功:表示接受了多少个字节
		失败:表示-1



5 销毁消息队列
	int msgctl(int msqid, int cmd, struct msqid_ds *buf);
	第一个参数:表示消息队列描述符
	第二个参数:表示给消息队列下达指令
		IPC_STAT : 表示获取消息队列属性
		IPC_SET  : 表示设置消息队列属性
		IPC_RMID : 表示销毁消息队列

===============================
共享内存:
创建共享内存
int shmget(key_t key, size_t size, int shmflg);
查看:
ipcs -m
删除:
ipcrm -m shmid
ipcrm -M key

映射内核态空间到进程的空间地址中
void *shmat(int shmid, const void *shmaddr, int shmflg);
第一个参数:表示共享内存id
第二个参数:表示映射空间地址 NULL
第三个参数:表示标志位 0
返回值:
成功:指想系统分配空间地址
失败:NULL

解映射 表示把共享内存从进程空间地址中删除
int shmdt(const void *shmaddr);

销毁
int shmctl(int shmid, int cmd, struct shmid_ds *buf);
IPC_RMID

内存空间重叠尽量使用memmove

RM销毁
练习:
1 父子进程循环操作数据 while
2 任意进化之间数据交换 file
3 传一个学生结构体 data
memcpy
memmove

信号量:
利用进程资源达到一种锁状态,也叫信号量锁

操作同一文件
父子进程操作:=> wait
多进程操作 : =>
10个进程 => 1000字符串 => 10000 ?

1 创建信号量锁
	int semget(key_t key, int nsems, int semflg);
	第一个参数:表示关键字 ftok
	第二个参数:表示信号量锁个数
	第三个参数:表示标志位
	返回值:
		

2 初始化锁变量
	int semctl(int semid, int semnum, int cmd, ...);
	第一个参数:表示信号量锁描述符
	第二个参数:表示锁的索引号 索引号从0开始
	第三个参数:表示指令
		SETVAL : 表示设置锁变量
	...		 : 表示对命令补充
		正数:表示锁开启状态
		负数:表示锁关闭状态
	返回值:
		成功:0
		失败:-1
3 设置加锁和解锁
	int  semop(int  semid,  struct  sembuf  *sops,  unsigned
	       nsops);
	第一个参数:表示信号量锁描述符
	第二个参数:表示信号量锁结构体
		表示锁索引号
		unsigned short sem_num;  /* semaphore number */
		表示加锁或者解锁
			正数:表示解锁
			负数:表示加锁
		short          sem_op;   /* semaphore operation */
		表示锁标志 0 快速互斥锁
		short          sem_flg;  /* operation flags */

	第三个参数:表示锁个数 1
	返回值:
		成功:0
		失败:-1

2019/12/11

9th
msg:
1 获取关键字
ftok
2 创建消息队列
msgget
3 发送消息
msgsnd
4 接受消息
msgrcv
5 销毁消息队列
msgctl

shm :
1 获取关键字
ftok
2 创建共享内存
shmget
3 映射
shmat
4 发送数据
strcpy memcpy memmove
5 获取数据
strcpy memcpy memmove
6 解映射
shmdt
7 销毁
shmctl

sem :
1 获取关键字
ftok
2 创建信号量锁
semget
3 初始化信号量锁
semctl
4 设置加锁和解锁
semop
5 销毁
semctl

=================================
线程:唯一表示就是线程号
就是一段可执行代码,并在内存中运行

一段程序中, 至少包括一个进程,而一个进程中至少包括一个线程

进程是资源管理的最小单位
线程是执行流的最小单位

进程安全性比线程高
线程执行效率比进程高

一个进程的异常退出,另一个进程在保护模式下不受影响。
一个线程的异常退出,则会导致同一进程的所有线程退出。

获取线程号
typedef unsigned long int pthread_t;
pthread_t pthread_self(void);

注意:
	编译的时候链接库文件 -lpthread

1 共享内存空间
2 动态性
3 并发行
4 异步性

创建一个线程:
int pthread_create(pthread_t *restrict thread, const pthread_attr_t *restrict attr, void *(start_routine)(void), void *restrictarg);
第一个参数:表示创建线程线程id
第二个参数:表示创建线程属性 NULL
第三个参数:表示创建线程执行函数
如果无须执行则NULL
第四个参数:表示给线程执行函数传递参数
如果不需要传递参数 NULL
返回值:
成功:0
失败:非零

线程退出:
void pthread_exit(void *value_ptr);(不能返回局部变量或运行时刻)

线程等待:
int pthread_join(pthread_t thread, void **value_ptr);
第一个参数:表示等待那个线程退出
第二个参数:表示等待线程退出返回值

线程销毁
int pthread_cancel(pthread_t thread);

======================================
线程互斥锁
动态锁:
初始化
int pthread_mutex_init(pthread_mutex_t *restrict mutex,
const pthread_mutexattr_t *restrict attr);
第一个参数:表示锁变量
第二个参数:表示锁的属性 NULL 快速互斥锁
成功:
0
销毁
int pthread_mutex_destroy(pthread_mutex_t *mutex);
参数:表示锁变量

	加锁:
		int pthread_mutex_lock(pthread_mutex_t *mutex);
	解锁:
		int pthread_mutex_unlock(pthread_mutex_t *mutex);
	尝试加锁
		int pthread_mutex_trylock(pthread_mutex_t *mutex);

静态锁:	
	pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

========================
清理函数
注册
void pthread_cleanup_push(void (routine)(void), void
*arg);
第一个参数:表示注册函数指针
第二个参数:表示给注册函数传递参数
执行
void pthread_cleanup_pop(int execute);
参数:
1 : 表示执行
0 : 不执行

注意:
	1 注册顺序和执行的顺序相反的
	2 执行顺序和代码位置有关
	3 之测函数和执行函数要一一对应

================================
网络编程:
就是套接子实现进程之间通讯 这就是网络编程

网络基础知识:

10th
应用层、表示层、会话层、传输层、网络层、数据链路层、物理层
应用层、传输层、网络互连层、主机到网络层
数据段 数据包 数据帧 比特

应用层 l文件传输: – FTP、TFTP
邮件服务: – SMTP、POP3
网络管理: – SNMP、Telnet、Ping、Tracert
网络服务: – HTTP、DNS、WINS

TCP:(Transmission Control Protocol/Internet Protocol)传输控制协议/互联网协议
而以太网最常用格式为 Ethernet II帧格式 ,所有第三层网络包都承载在其数据段之中 – Ethernet II类型以太网帧的最小长度为64字节(6+6+2+46+4),最大长度为1518字 节(6+6+2+1500+4)。其中前12字节分别标识出发送数据帧的源节点MAC地址和接 收数据帧的目标节点MAC地址。

以太网帧格式:
目标的MAC地址:表示确认目标证的接受者
源的MAC地址  :表示发送帧的工作站
类型		 :表示接受设备如何解析数据字符
数据		 :
	数据帧	 :帧头 + IP数据包 + 帧尾
			 帧头:包括源和目标的MAC地址以及类型。
			 帧尾:表示校验位
	IP数据包 :IP包头 +  TCP数据信息
			IP包头 : 源和目标的IP地址 类型 生存周期...
	TCP数据包: TCP包头 + 实际数据
			TCP包头 : 源和目标端口号 帧序列 确认号 校验位。
校验位       : 
最小64个字节 最大1518个字节

机器地址(machine address)
创建线程:
int pthread_create(pthread_t *restrict thread, const pthread_attr_t *restrict attr, void *(start_routine)(void), void *restrictarg);

线程退出
void pthread_exit(void *value_ptr);
线程等待
int pthread_join(pthread_t thread, void **value_ptr);
线程处理函数
void pthread_cleanup_pop(int execute);
void pthread_cleanup_push(void (routine)(void), void
*arg);
线程互斥锁
动态锁
int pthread_mutex_destroy(pthread_mutex_t *mutex);
int pthread_mutex_init(pthread_mutex_t *restrict mutex,
const pthread_mutexattr_t *restrict attr);
静态锁
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

加锁和解锁
int pthread_mutex_lock(pthread_mutex_t *mutex);
int pthread_mutex_trylock(pthread_mutex_t *mutex);
int pthread_mutex_unlock(pthread_mutex_t *mutex);

注意:编译的时候要连接库文件 -lpthread

===============================
OSI7层互联网络参考模型
由底到高
物理层:检测物理线路,确保数据发送
集线器:
1 放大信号
2 扩展物理接口
数据链路层:保证数据在物理线路上的可靠传输
作用包括物理编址 网络拓扑结构 错误校验 帧序列以及流控。
编址:
统一编址
独立编址
拓扑结构:
总线型
星型
环形
错误校验:
奇偶校验
和校验

		交换机:
			自动寻址和交换作用
	网络层:
		就是把网络ip地址转换成MAC地址 这叫地址解析协议

		路由器:
			地址翻译 协议转换 数据格式转换等
	传输层:
		实现用户之间的数据交换 TCP UDP
	会话层:保证数据链接
		会话层所使用服务可使应用建立和位置会话,并使数据获得同步。
	表示层:数据体现方式
		加密和解密 压缩和解压缩。。。
	应用层:数据用户接口,也就是应用层用户程序编辑接口

TCP/IP网络模型
	传输层:
	会话层:
	表示层:
	应用层:

=========================================
以太网帧格式:
目标的MAC地址:表示确认目标证的接受者
源的MAC地址 :表示发送帧的工作站
类型 :表示接受设备如何解析数据字符
数据 :
数据帧 :帧头 + IP数据包 + 帧尾
帧头:包括源和目标的MAC地址以及类型。
帧尾:表示校验位
IP数据包 :IP包头 + TCP数据信息
IP包头 : 源和目标的IP地址 类型 生存周期…
TCP数据包: TCP包头 + 实际数据
TCP包头 : 源和目标端口号 帧序列 确认号 校验位。
校验位 :

最小64个字节 最大1518个字节

IP :
动态指定:
静态指定:

查看网卡信息
ifconfig
重启网络服务:
redhat : service network restart
Ubuntu : /etc/init.d/networking restart
网卡配置文件
/etc/sysconfig/network-scripts/ifcfg-eth0 表示第一张网卡文件
# Advanced Micro Devices [AMD] 79c970 [PCnet32 LANCE]
#表示网卡名
DEVICE=eth0
#指定ip分配方式 static 表示静态 dhcp 表示动态
BOOTPROTO=static
#BOOTPROTO=dhcp
#MAC地址
HWADDR=00:0C:29:F9:9F:7C
#表示是否启动这张网卡
ONBOOT=yes
#表示默认子网掩码
NETMASK=255.255.255.0
#表示指定IP地址
IPADDR=192.168.0.254
#表示默认网关
GATEWAY=192.168.0.1
#表示网络协议
TYPE=Ethernet

===========================
tcp : 面向连接服务

客户端:
	1 创建网络套接子
		int socket(int domain, int type, int protocol);
		第一个参数:表示地址家族
			PF_INET : 表示IPV4地址家族
		第二个参数:表示类型
			SOCK_STREAM : 表示流式套接子类型         	TCP	   O//ctrl + p :  自动补全
			SOCK_DGRAM	: 表示数据报套接子类型			//UDP
			SOCK_RAW	: 表示原始套接子
		第三个参数:表示端口协议 0
			tcp : 0 and IPPROTO_TCP
			udp : 0 and IPPROTO_UDP
		返回值:
			成功:文件描述符
			失败:-1
	2 请求建立连接
		int    connect(int   sockfd,   const   struct   sockaddr
		       *serv_addr, socklen_t addrlen);

		第一个参数:表示套接子文件描述符 socket的返回值
		第二个参数:套接子地址结构体
		struct sockaddr_in {														//结构体大小16个字节,有隐藏,
		
			表示地址家族
			sa_family_t    sin_family; /* address family: AF_INET */
			表示端口号 0 ~ 65535  => 
			u_int16_t      sin_port;   /* port in network byte order */
			表示网络ip地址 "192.168.0.254" => 
			struct in_addr sin_addr;   /* internet address */
		};

		/* Internet address. */
		struct in_addr {
			u_int32_t      s_addr;     /* address in network byte order */
		};
		===============
		struct sockaddr {
		    sa_family_t sa_family;  /* address family, AF_xxx   */
			    char        sa_data[14];    /* 14 bytes of protocol address */
				};

		主机字节序改变成网络字节序
		uint32_t htonl(uint32_t hostlong);  长格式
		uint16_t htons(uint16_t hostshort); 短格式

		把网络字节序转换成主机字节序
		uint32_t ntohl(uint32_t netlong);	长格式
		uint16_t ntohs(uint16_t netshort);  短格式

		数据存储方式不一致
		网络存储方式一般是大端模式
		主机存储方式一般是小端模式
		大端模式:
			高字节存储在底地址中 或者底字节存储在高地址中
		小端模式:
			高字节存储在高地址中 或者底字节存储在底地址中

		int a = 0x12345678;
		主机ip地址转换成网络ip地址
		in_addr_t inet_addr(const char *cp);
		in_addr_t inet_network(const char *cp); 网络二进制ip地址
		网络ip地址转换成主机ip地址
		char *inet_ntoa(struct in_addr in);
	
		第三个参数:表示套接子结构体空间大小
		返回值:
			成功:0
			失败:-1

服务器:
	1 创建套接子 表示用于连接用户
		socket
	2 帮定端口号
		int  bind(int  sockfd,  const  struct sockaddr *my_addr,
		       socklen_t addrlen);

		第一个参数:表示套件字文件描述符
		第二个参数:表示服务套接子结构体空间地址
		第三个参数:表示空间大小
		返回值:
			成功 0
			失败 -1
	3 监听
		int listen(int sockfd, int backlog);
		第一个参数:表示套接子文件描述符
		第二个参数:表示监听客户端个数
	
	4 连接
		int  accept(int sockfd, struct sockaddr *addr, socklen_t
		       *addrlen);

		第一个参数:表示创建套接子文件描述符
		第二个参数:表示套接子结构体 目标结构体
		第三个参数:表示空间大小 指针
		返回值:
			成功:返回未使用最小文件描述符 用于处理数据
			失败: -1

练习:
传送一个文件
client => server => output
homework :
实现网络聊天 zhangsan lisi
实现ssh远程登录
15:21 2019/12/12
客户端
1、创建套接字 socket
2、请求建立连接 connent

ipv4是4个byte,ipv6是16byte

man socket
man 7 ip
man htons

service httpd restart
service httpd stop

服务器
1、创建套接字 表示连接用户
socket
2、绑定端口号
bind
3、监听客户链接
int listen
4、连接
accept

真正网络通讯是文件描述符

/etc/s
11th
net :
三次握手实现原理
第一次握手:客户端向服务器发送一个SYN包(请求建立连接) SYN => 1 seq => X
第二次握手:服务器接受SYN包 会向客户端发送ACK包(确认包) ACK => 1 my_seq => Y SYN => 1 ack_seq => X + 1
第三次握手:客户端接受到服务器ACK包 ,再向服务器发送一个ACK包,ACK => 1 SYN => 0 ack_seq => y + 1 data => x + 1

tcp :
1 客户端
1 socket
2 connect
3 write / read
4 close

2 服务器
	1 socket 
	2 bind
	3 listen
	4 accept
	5 write / read
	6 close

=============================
网络套接子发送
ssize_t send(int s, const void *buf, size_t len, int
flags);
第一个参数:表示套接子文件描述符
第二个参数:表示发送数据空间地址
第三个参数:表示数据大小
第四个参数:表示标志位 0
返回值:
成功:表示发送数据个数
失败:-1
接受
ssize_t recv(int s, void *buf, size_t len, int flags);
第一个参数:表示套接子文件描述符
第二个参数:表示接受数据空间地址
第三个参数:表示空间大小
第四个参数:表示标志位 0
返回值:
成功:表示接受多少个字节
失败:-1 | 0 表示退出

UDP:
客户端:
1 创建套接子
2 发送数据
ssize_t sendto(int s, const void *buf, size_t len, int
flags, const struct sockaddr *to, socklen_t tolen);

		第一个参数:表示套接子描述符
		第二个参数:表示接受数据空间地址
		第三个参数:表示空间大小
		第四个参数:标志位 0
		第五个参数:结构体
		第六个参数:结构体大小
		返回值:
			成功:发送字节数
			失败:-1


			
服务器:
	1 创建套接子
		socket
	2 帮定服务端口
		bind
	3 接受数据	
	ssize_t recvfrom(int s, void *buf, size_t len, int flags,
	                        struct sockaddr *from, socklen_t *fromlen);
		第一个参数:表示套接子文件描述符
		第二个参数:表示发送数据空间地址
		第三个参数:表示数据长度
		第四个参数:表示标志位 0
		第五个参数:表示套接子结构体信息
			struct sockaddr_in => 
				
		第六个参数:表示结构体大小  16
		返回值:
			成功:表示发送数据个数(字节)
			失败:-1

	4 关闭

练习:
	实现文件传输 
	实现tell

=========================================
broadcast: udp

案例:循环播放文件
广播地址:192.168.0.255
send :
			
	套接子设置为广播属性
	int setsockopt(int s, int level, int optname, const void
	       *optval, socklen_t optlen);
	第一个参数:表示套接子文件描述符
	第二个参数:表示级别
		SOL_SOCKET : 表示基本套接子 *
		IPPROTO_TCP : 表示tcp套接子
		IPPROTO_UDP :  表示udp套接子
		IPPROTO_IP  : 表示ipv4套接子
		IPPROTO_IPV6 :表示ipv6套接子
	第三个参数:表示操作方式
		SO_BROADCAST
	第四个参数:表示开关
		1 : 表示打开
		0 : 表示关闭
	第五个参数:表示开关参数大小
	返回值:
		成功0
		失败:-1

recv:

=====================
多播 组播
多播地址:224.1.2.3

发送端:
	设置成多播
接受端:
	添加用户到多播组中
	struct ip_mreqn {
		表示多播组号
		struct in_addr imr_multiaddr; /* IP multicast group
										 address */
		表示用户ip地址								 
		struct in_addr imr_address;   /* IP address of local
										 interface */
		表示序列 0								 
		int            imr_ifindex;   /* interface index */
	};
	表示添加IP地址到目标中
	int inet_pton(int af, const char *src, void *dst);
	第一个参数:表示地址家族 AF_INET
	第二个参数:表示IP地址 
	第三个参数:表示把源ip地址赋值给目标地址

	int inet_aton(const char *cp, struct in_addr *inp);
	第一个参数:表示ip地址
	第二参数:表示

注意:必须设置默认网关

==========================================
IO复用
多文件描述符管理
int select(int nfds, fd_set *readfds, fd_set *writefds,
fd_set *exceptfds, struct timeval timeout);
第一个参数:表示文件描述符最大值 + 1
第二个参数:表示读集
第三个参数:表示写集
第四个参数:表示错误集合
第五个参数:表示时间结构体
struct timeval {
表示秒
long tv_sec; /
seconds /
表示微妙
long tv_usec; /
microseconds */
};
NULL : 表示阻塞方式等待
0 0 : 表示无阻塞
2 2 : 表示时间到后就执行
返回值:
成功:文件描述符个数
失败:-1

void FD_CLR(int fd, fd_set *set); 	表示从集合中删除
int FD_ISSET(int fd, fd_set *set); 	表示判断是否在集合中
void FD_SET(int fd, fd_set *set);	表示添加到集合中
void FD_ZERO(fd_set *set);			表示清空集合
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值