当前位置: 首页 > news >正文

长春网站建设推荐网诚传媒北京响应式网站建设

长春网站建设推荐网诚传媒,北京响应式网站建设,wordpress培训,wordpress怎样获取文章分类的id绪论​ “宿命论是那些缺乏意志力的弱者的借口。 ——罗曼#xff0e;罗兰”#xff0c;本章是为应用层打基础#xff0c;因为在写应用层时将直接通过文本和代码的形式来更加可视化的理解网络#xff0c;本章主要写的是如何使用网络套接字和udp、tcp初步认识。 话不多说安… 绪论​ “宿命论是那些缺乏意志力的弱者的借口。 ——罗曼罗兰”本章是为应用层打基础因为在写应用层时将直接通过文本和代码的形式来更加可视化的理解网络本章主要写的是如何使用网络套接字和udp、tcp初步认识。 话不多说安全带系好发车啦建议电脑观看。 1.理解套接字 套接字 ip 端口 我们所有的网络通信行为本质就是进程间通信 对双方而言 先把数据能到达自己的主机ip找到指定的进程port端口号IP地址用来标识互联网中唯一的一台主机端口号用来标识该指定的机器中进程的唯一性所以{ipport}ipport互联网中唯一一台主机的进程套接字socket 在互联网中通过套接字进行通信也就类似于是网络中的进程通信 2.认识端口号 端口是是一个16位的数字uint16_t port它用来标识当前主机上的唯一的一个网络进程以及让网络进程 和 port进行绑定关联让接收方确认是发给自己的某个进程 2.1pid vs port 不难发现pid和port非常类似但区分出来的原因是 进程管理 和 网络管理 进行解耦防止OS中进程改变影响网络通信port用来专门进行网络通信一个端口号只能和一个进程相关联反之一个进程可以和多个端口号相关联 socket可以理解成打10086 转人工工号其中10086相当于ip、人工相当于port 3.TCP协议 1. 有连接 2. 可靠传输tcp面对异常他会进行可靠性处理丢包了重传乱序了排成有序 …但也意味着复杂要做更多的工作 3. 面向字节流 4.UDP协议 1. 无连接 2. 不可靠传输反之发数据后不管数据是否异常(丢包,乱序…(也意味着简单适合于对数据可靠性要求不高的场景(直播)) 3. 面向数据报 tcp、udp只有不同没有好坏分情况使用。 5.网络字节序 在网络中可能会有大端存储小端存储 不懂的建议观看这篇blog 存储的方式可能因为不同的机器存储方案也是不同的 其中在网络中 发送主机通常将发送缓冲区中的数据按内存地址从低到高的顺序发出接收主机把从网络上接到的字节依次保存在接收缓冲区中也是按内存地址从低到高的顺序保存总结上述意思就是组织规定了所有到达网络的数据必须是大端所有从网络收到数据的机器都会知道数据是大端这样也能方便的查看数据 6.socket编程接口 6.1UDP协议 网络编程的时候socket是有很多类型的 unix socket域间socket-同一台主机上的文件路径命名管道本主机内部进行通信网络socket主要使用ipport进行网络通信用的是传输层和网络层(tcp、udp)原始socket编写一些网络工具应用层跳过传输层不进行网络通信直接到达网络层和数据链路层 网络编程的时候是由不同的场景的理论上而言我们应该给每种场景设计一套编程接口而设计者只想用一套接口改变传递参数就能实现找到对应的结构基础的结构是struct sockaddr struct socket是一个通用的地址类型 通过判断前两个字节16位地址类型来判断是哪一种类型 当第一个参数是AF_INET表示网络通信当第一个参数是AF_UNIX域间套接 上述用的都是同一套API: 常用的socket套接字函数能写UDP协议了 int socket(int domain, int type, int protocol); 1. 头文件#include sys/types.h、#include sys/socket.h 2. domain设置通信的协议AF_INET网络通信、AF_UNIX域间套接 3. type套接字类型SOCK_STREAM流式套接TCP常用、SOCK_DGRAM面对数据报提供数据报协议UDP、SOCK_RAM原始套接 4. protocol表示使用的那个tcp/udp协议通过前面两个参数已经能确定是那个协议了故可直接写成0 int bind(int sockfd, const struct sockaddr *addr , socklen_t addrlen); 1. 头文件#include sys/types.h、#includesys/socket.h 2. sockfd创建的网络套接字 3. addrlen传入结构体的长度 4. addr sockaddr_in的结构其中包括了 1. sin_familyAF_INET;//协议家族 绑定网络通信的信息 2. sin_port 3. s_addr 所以对sockaddr_in localaddr初始化写成具体细节已注释 //补充结构体sockaddr_inbzero(local,sizeof(local));//将指定的空间的大小内存清零local.sin_family AF_INET;//协议家族 绑定网络通信的信息//sinssocket ininetIP地址local.sin_port htons(_port);//将string的_port转换成网络序列通过htons h:host、to、n:net、s:socketlocal_sin_addr.s_addr inet_addr(_ip);//需要把uint16_t的ip转化成4字节的uint32_t的网络序列的ip可以通过inet_addr 第一个参数sin_family就是sockaddr_in将sa_prefix传进宏和family进行拼接得 初始化成AF_INET表示绑定网络通信。 第二个参数sin_port初始化为_port主机转网络序列用函数htons。 第三个参数sin_addr.s_addr通过in_addr的结构知道还要对s_addr初始化成32位4byte。初始化为把ip转换成32位并且网络序列化直接用函数inet_addr。 附 函数void bzero(void *s, size_t n) 作用将指定内存全部清零、头文件#includestrings.h 接收用户信息函数 ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr *src_addr, socklen_t *addrlen);sockfd创建的sock文件buf缓冲区获取用户发来的信息len期望大小返回值才是实际大小flags收数据的模式默认设为0阻塞式收消息src_addr输出型参数接收到发送端的套接字信息ip、portaddrlen传入结构体的长度 发送用户信息函数 ssize_t sendto(int sockfd, const void *buf, size_t len, int flags, const struct sockaddr *dest_addr, socklen_t addrlen);参数和上面都一样不过诉了不同点 dest_addr填写要发给的对象信息服务器可以先通过接收到的发送端信息直接填写而客户端则是将提前得知的服务器的信息填写进去 6.1.1编写服务器和客户端的代码 UdpServer.hpp: #pragma once #includeiostream #includestring #includeunistd.h #includestrings.h#include sys/types.h #include sys/socket.h #include netinet/in.h #include arpa/inet.h#includecerrno #includecstring#includeComm.hpp #includenocopy.hpp #includeLog.hppusing namespace std;static const uint16_t defaultport 8888; static const uint16_t defaultfd -1; static const int defaultsize 1024; class UdpServer : public nocopy { public:UdpServer(const string ip,uint16_t port defaultport):_ip(ip),_port(port),_sockfd(defaultfd){}void Init(){//1. 创建套接字,创建成功后会返回 a ffile descriptor 出错返回-1_sockfd socket(AF_INET,SOCK_DGRAM,0);//SOCK_DGRAM : udpif(_sockfd 0)//创建套接字失败{lg.LogMessage(Fatal,socket errno, %d : %s\n,errno,strerror(errno));exit(Socket_Err);}lg.LogMessage(Info,socket success,sockfd : %d\n,_sockfd);//2. 绑定指定网络信息 相当于给套接字命名struct sockaddr_in local;//该结构体 需要新加头文件#include netinet/in.h、#include arpa/inet.h//补充结构体sockaddr_inbzero(local,sizeof(local));//将指定的空间的大小内存清零local.sin_family AF_INET;//协议家族 绑定网络通信的信息//sinssocket ininetIP地址local.sin_port htons(_port);//将string的_port转换成网络序列通过htons h:host、to、n:net、s:socketlocal.sin_addr.s_addr inet_addr(_ip.c_str());//需要把uint16_t的ip转化成4字节的uint32_t的网络序列的ip可以通过inet_addr//将刚刚设置好的网络信息和的sockfd文件信息进行绑定int n ::bind(_sockfd,(struct sockaddr*)local,sizeof(local));if(n ! 0){lg.LogMessage(Fatal,bind errno, %d : %s\n,errno,strerror(errno));exit(Bind_Err);} //绑定完成后就服务器就已经初始化完成了}void Start() {char buffer[defaultsize];//服务器永远不退出for(;;){ //服务器进行udp收发消息struct sockaddr_in peer;socklen_t len sizeof(peer);//socklen_t 就是无符号整形ssize_t n recvfrom(_sockfd,buffer,sizeof(buffer)-1,0,(struct sockaddr*)peer,len);if(n 0){ buffer[n] 0;//当字符串cout client say# buffer endl;//给对方发消息sendto(_sockfd,buffer,sizeof(buffer)-1,0,(struct sockaddr*)peer,len);}}}~UdpServer(){} private:string _ip;uint16_t _port;int _sockfd; };UdpClient.cc #include iostream#include sys/types.h /* See NOTES */ #include sys/socket.h #include arpa/inet.h #include netinet/in.h#include cstring #include unistd.h #include cerrno using namespace std;void Usage(const string process) {cout Usage: process server_ip server_ip endl; }//./udp_client server_ip server_port 向服务器发消息 int main(int argc, char **argv) {if (argc ! 3){Usage(argv[0]);return 1;}string serverip argv[1]; // 字符串的点分十进制uint16_t serverport stoi(argv[2]);// 1. 创建套接字,创建文件信息int sock socket(AF_INET, SOCK_DGRAM, 0);if (sock 0){cerr socket error: strerror(errno) endl;return 2;}cout create socket success: sock endl;// 2. 绑定// 其中客户端的socket也要绑定但是不需要显示bindclient会在首次发送数据的时候会自动进行bind// 不推荐自己绑定为什么服务器的端口号一定是众所周知的不可改变。而client 需要 port让其随机bind端口// client一般不绑定一个确定的socket因为client 会非常多打开如何软件可能会导致别人占了你的端口// 就导致无法启动// 2.1 填充server信息struct sockaddr_in server;memset(server,0,sizeof(server));server.sin_family AF_INET;server.sin_port htons(serverport);server.sin_addr.s_addr inet_addr(serverip.c_str());while (true){string inbuffer;cout Please Enter# ;getline(cin, inbuffer);// 发给int n sendto(sock,inbuffer.c_str(),inbuffer.size(),0,(struct sockaddr*)server,sizeof(server));if(n0)//发送成功{char buffer[1024];//收消息struct sockaddr_in temp;socklen_t len sizeof(temp);ssize_t m recvfrom(sock,buffer,sizeof(buffer)-1,0,(struct sockaddr*)temp,len);//虽然没用但也是要填的tempif(m 0){buffer[m] 0;cout server echo# buffer endl;}else break;}} close(sock); // 把文件描述符关掉return 0; }nerstat -anup查看网络连接网络情况的指令 -a所有信息 nnum将主机名转换为数字化 pprocess信息 uudp 当把ip设置为127.0.0.1表示在当前主机内进行本地通信 再对代码进行优化当客户端发来信息时显示客户端的socket //... class UdpServer : public nocopy { public:UdpServer(const string ip,uint16_t port defaultport):_ip(ip),_port(port),_sockfd(defaultfd){}void Init(){//...}void Start() {char buffer[defaultsize];//服务器永远不退出for(;;){ //服务器进行udp收发消息struct sockaddr_in peer;socklen_t len sizeof(peer);//socklen_t 就是无符号整形ssize_t n recvfrom(_sockfd,buffer,sizeof(buffer)-1,0,(struct sockaddr*)peer,len);if(n 0){ InetAddr addr(peer);//新写一个类对类进行封装buffer[n] 0;//当字符串cout [ addr.PrintDebug() ]# buffer endl;//调用该类中类函数//给对方发消息sendto(_sockfd,buffer,sizeof(buffer)-1,0,(struct sockaddr*)peer,len);}}}~UdpServer(){} private:string _ip;uint16_t _port;int _sockfd; };InetAddr.hpp: #pragma once #includeiostream #includestring #include sys/types.h #include sys/socket.h #include netinet/in.h #include arpa/inet.h #includeunistd.husing namespace std;class InetAddr { public:InetAddr(struct sockaddr_in addr){port ntohs(addr.sin_port);ip inet_ntoa(addr.sin_addr);//将网络序列转化成addr}string IP(){return ip;}uint16_t Port(){return port;}string PrintDebug(){string info ip;info :;info to_string(port);return info;}private:string ip;uint16_t port; };云服务器公网IP其实是供应商给你虚拟出来的公网ip无法bind 如果你是真的Linux环境可以直接bind你的ip但强烈不建议给服务器bind固定ip这样服务器和特定ip绑死后就只能收到该绑定的机器的信息更推荐本地任意ip绑定的方式 所以我们能修改UdpServer.hpp的代码 把UdpServer的成员变量ip取消掉local.sin_addr.s_addr inet_addr(_ip.c_str());并且把ip绑定成INADDR_ANY0local.sin_addr.s_addr INADDR_ANY; //...// 优化代码不绑定特定的ip class UdpServer : public nocopy { public:UdpServer(uint16_t port defaultport):_port(port),_sockfd(defaultfd){}void Init(){ //...local.sin_addr.s_addr INADDR_ANY;//一般不固定一个ip而是任意生成一个ip的动态绑定INADDR_ANY 0 // local.sin_addr.s_addr inet_addr(_ip.c_str());//需要把uint16_t的ip转化成4字节的uint32_t的网络序列的ip可以通过inet_addr//...}void Start() { //...}~UdpServer(){} private:// string _ip;uint16_t _port;int _sockfd; };Makefile: 主函数 #includeUdpServer.hpp #includememory #includestring #includeComm.hpp using namespace std;void Usage(string proc) {cout Usag : \n\t proc local_ip local_port\n endl; }//./udp_sv 8888 int main(int argc,char* argv[]) {if(argc ! 2){Usage(argv[0]);return Usage_Err;}string ip argv[1];uint16_t port stoi(argv[2]);unique_ptrUdpServer usvr make_uniqueUdpServer(port);usvr-Init();usvr-Start();return 0; }Makefile: .PHONY:all all:udp_server udp_clientudp_server:Main.ccg -o $ $^ -stdc14udp_client:UdpClient.ccg -o $ $^ -stdc14.PHONY:clean clean:rm -f udp_server udp_client其中服务器的ip为0.0.0.0表示任意ip地址绑定 可以通过在别的客户端上对该服务器进行发送消息只需要知道当前服务器的ip和端口并且有当前客户端的可执行程序 云服务器中大部分端口号是被腾讯云、阿里云…拦截的。 我要能够进行数据的发送需要开放指定的多个端口 8080、8081、… 6.2TCP协议 除UDP以学的外主要新增有 在socket函数创建文件时第二个参数使用SOCK_STREAM提供序列化的、可靠的、双方的、建立链接的字节流 int sockfd socket(AF_INET,SOCK_STREAM,0);Server端c/s双方要进行通信得先建立连接接收client的连接 int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);sockfd sock文件addr 和 addrlen 与recvfrom中的参数一样头文件#include sys/types.h、#include sys/socket.h返回值成功后会返回一个新增的文件描述符accepted socket失败返回-1并设置错误码而该返回的文件描述符sockfd就是用来将server获取新链接sockfd在该内部进行服务的处理我们创建的listensock只是用来找到client的 用来侦听功能将套接字置于侦听传入连接的状态 int listen(int sockfd, int backlog);sockfdsock文件 backlog后面会具体写暂时只要知道在tcpServer中肯定要写 Client端连接到服务器 int connect(int sockfd, const struct sockaddr *addr,socklen_t addrlen);头文件#include sys/types.h、#include sys/socket.h 成功返回0否则返回-1错误码被设置 对于客户端来说并不需要自己绑定bindip和portclient系统会随机一个端口 当我们在发起连接的时候client会被OS自动进行本地绑定 附 inet_pton 和 inet_addr类似都能把四字节的字符串ip转化成网络序列 int inet_pton(int af, const char *src, void *dst);af通信的协议(AF_INET网络通信)src来源写ipdst目的的写local.sin_addr头文件#include arpa/inet.h 6.2.1基本tcp实现通信 Client.cc #include iostream #include string #include cstring #include cstdlib #include stdio.h #include unistd.h#include sys/types.h #include sys/socket.h #include netinet/in.h #include arpa/inet.h #include Comm.hpp #include Log.hppusing namespace std;int main(int argc , char*argv[]) {if(argc ! 3){cout Usag: \n\t argv[0] local_ip local_port \n endl;return Usage_Err;} string serverip argv[1];int serverport atoi(argv[2]);//1. 创建套接字socketint sockfd socket(AF_INET,SOCK_STREAM,0);if(sockfd 0){lg.LogMessage(Fatal,create sock errorr, %d : %s\n,errno,strerror(errno));exit(Fatal);}//2. connect //不用bind 系统在local的时候会自动bindstruct sockaddr_in local;memset(local,0,sizeof(local));local.sin_family AF_INET;local.sin_port htons(serverport); inet_pton(AF_INET,serverip.c_str(),local.sin_addr);int n connect(sockfd,CONV(local),sizeof(local));if(n 0){cout connect error endl;return 2;}while(true){string inbuffer;cout Pleace Enter# ;getline(cin,inbuffer);ssize_t n write(sockfd,inbuffer.c_str(),inbuffer.size());//直接使用sockfdif(n 0){char buffer[1024];ssize_t m read(sockfd,buffer,sizeof(buffer)-1);//直接使用sockfdif(m 0){buffer[m] 0;//将最后位置写个0作为结束标志 cout get a echo message - buffer endl;}else{break;}}else{cout write error endl;break;}}close(sockfd);return 0; }Server.hpp #pragma once#include iostream #include string #include cstring #include cerrno #include unistd.h#include sys/types.h #include sys/socket.h #include netinet/in.h #include arpa/inet.h #include Log.hpp #include nocopy.hpp #include Comm.hppstatic const int default_backlog 5;class TcpServer : public nocopy { public:TcpServer(uint16_t port):_port(port),_isrunning(false){}void Init(){//创建sock文件_listensock socket(AF_INET,SOCK_STREAM,0);if(_listensock 0){lg.LogMessage(Fatal,create sock errorr, %d : %s\n,errno,strerror(errno));exit(Fatal);} lg.LogMessage(Debug,create sock success, sock:%d\n,_listensock);//填充本地信息并bind给内核struct sockaddr_in local;memset(local,0,sizeof(local));local.sin_family AF_INET;local.sin_port htons(_port);//将整形转化成网络序列local.sin_addr.s_addr htonl(INADDR_ANY);//0 //bind sock文件和网络序列if(bind(_listensock,CONV(local),sizeof(local)) ! 0){lg.LogMessage(Fatal,bind error, %d : %s\n,errno,strerror(errno));exit(Bind_Err);}lg.LogMessage(Debug,bind success,sock: %d\n,_listensock);//设置socket为监听模式tcp特有的if(listen(_listensock,default_backlog) ! 0){lg.LogMessage(Fatal,listen error, %d : %s\n,errno,strerror(errno));exit(Listen_Err);}lg.LogMessage(Debug,listen success,sock: %d\n,_listensock);}//Tcp连接全双工通信void Service(int sockfd){char buffer[1024];while(true){ssize_t n read(sockfd,buffer,sizeof(buffer));if(n 0){buffer[n] 0;cout client echo# buffer endl;string echo_string server echo# ;echo_string buffer;write(sockfd,echo_string.c_str(),echo_string.size());}else if(n 0){lg.LogMessage(Info,client quit...\n);break;}else{lg.LogMessage(Error,listen error, %d : %s\n,errno,strerror(errno));break;}}}void Start(){_isrunning true;while(_isrunning)//_listensock相当于是负责拉客的人找到客人返回的文件描述符{//获取连接struct sockaddr peer;socklen_t len sizeof(peer);int sockfd accept(_listensock,CONV(peer),len);//sockfd才是提供服务的服务员if(sockfd 0){lg.LogMessage(Fatal,accept fail,%d : %s\n,errno,strerror(errno));continue;}lg.LogMessage(Debug,accept success,sock: %d\n,_listensock);//提供服务 v1 ~ v4 Service(sockfd);close(sockfd);}}~TcpServer(){}private: int _listensock;uint16_t _port;bool _isrunning; };Makefile: .PHONY:all all:tcp_server tcp_clienttcp_server:Main.ccg -o $ $^ -stdc14 -lpthreadtcp_client:TcpClient.ccg -o $ $^ -stdc14 -lpthread.PHONY:clean clean:rm -f tcp_server tcp_clientMain.cc 此处要通过Main.cc 启动服务器 #include iostream #include memory #include string #include stdio.h#include TcpServer.hpp #include Comm.hppusing namespace std;int main(int argc,char* argv[]) {if(argc ! 2){cout Usag: \n\t argv[0] local_port\n endl;return Usage_Err;}uint16_t port stoi(argv[1]);unique_ptrTcpServer tsvr(new TcpServer(port)); // 另外的使用方式//unique_ptrTcpServer tsvr make_uniqueTcpServer(port);tsvr-Init();tsvr-Start();return 0; }测试结果 通过netstat -nltp可以查看已有的网络链接 1. IO类函数write/read其实他们已经做了转网络序列 2. udp用户数据报数据都是一个个报文的发送、tcp面向字节流数据一次发一条数据这些数据可能是一个报文也可能是不完整的报文后面通过边界来找到对应的 1. sendto、recvfrom - sendto 发了一次一定对应对端recvfrom一次面向数据报类似于发邮件、快递一件一件的 2. write - 写了1,10,…次 接收方read可能一次就全部收完了也可能多次无论多少次和对方发的无关面向字节流 类似于使用的自来水用多少取决于自己 3. 我们的网络服务不能在bash中以前台进程的方式运行真正的服务器必须在Linux后台以 守护进程精灵进程的方式持续不断的运行 守护进程 会话与进程组 查看已用进程查看sleep通过ps查看在通过管道grep和head过滤出进程sleep和ps的第一行 ps -ajx | head -1 ps ajx | grep sleep同时创建的进程会在同一个会话中其中第一个创建的进程组id和他的pid一样和会话id就是所有进程的进程组id和会话id 每次登录Linux - OS 会给登录用户提供 bash提供一个终端给用户提供命令行解析-叫做一个会话在命令行中启动的所有的进程最终默认都是在当前会话内部的一个进程组可以是一个进程自成进程组 任何时刻一个会话内部可以存在很多个进程组用户级任务但是默认如何时刻只允许一个进程组在前台前台进程组 通过在启动进程是 加 让其进程组变成后台进程 查看后台进程 jobs其中第一列的序号就是后台进程的编号 将后台进程放回前台 fg 后台进程编号其中注意的是 bash也是一个进程组 而一个会话中只能有一个进程组在前台 所以当sleep的进程组从后台到前台后bash就无法使用了而前台是和终端和键盘相关可以通过键位再把当前进程组放回后台直接发送终止信号终止进程 ctrl z此时bash会自动被放回前台并且发现其状态变成了Stopped所以需要再把状态调回Runing bg 进程组编号用户级任务 Vs 进程组它们是一个概念只不过进程组更加的专业化进程组就是实现现有的任务。 会话相当于开的一个窗口其前台进程一开始就是bash若要再创建进程就是在该会话内创建。 守护进程的作用以及实现原理 若想要服务器不受用户登录和注销的影响 就只能使用守护进程它就是一个独立的会话不隶属于任何bash的会话将前面写的tcpserver、udpserver守护进程化进程守护话后表示该服务即使会话关闭后也仍然存在也就相当于一个后台服务24h的云服务器 创建一个会话并且设置自己为会话的首进程这样会话id和进程组id与该进程的会话id相同若要创建一个新的会话调用进程不能是一个组长 组长一般是多个进程的第一个若只有一个进程自成进程组那组长自然就是自己 所以要创建子进程fork再让父进程终止这样子进程就既不是组长了并且会话也只有一个进程所以守护进程就一定是孤儿进程系统是父进程 ppid:1因为守护进程和当前目录无关所以可以把其目录改成根目录当然也能不进行修改 4. 对于守护进程不需要和用户进行输入输出错误的关联了所以就能关闭或者重定向到null文件因为写到null文件null字符设备中的都会被丢弃凡是从null文件中拿的都是空该文件目录为/dev/null 模拟实现守护进程 #pragma once//Daemon 守护、精灵 #include signal.h #include unistd.h #include cstdlib#include sys/types.h #include sys/stat.h #include fcntl.hconst char* root /; const char* dev_null /dev/null;//守护进程的核心5个步骤 void Daemon(bool ischdir,bool isclose) { //1. 忽略可能出错的信号signal(SIGCHLD,SIG_IGN);signal(SIGPIPE,SIG_IGN);//2. 关闭父进程if(fork() 0) exit(0);//3. 变成组长setsid();//4. 每一个进程都有自己的cwd是否将当前进程cwd改成 / 根目录if(ischdir) chdir(root);//5. 已经变成守护进程了就不需要和用户进行输入输出错误的关联了if(isclose){close(0);close(1);close(2);}else//一般就直接把他们重定向到O_RDWR{int fd open(dev_null,O_RDWR);if(fd 0)//文件打开成功{dup2(fd,0);dup2(fd,1);dup2(fd,2);close(fd);}}}//main.cc #include Daemon.hpp #include unistd.hint main() {//变成守护进程Daemon(true,false);while(true){ //要执行的核心代码}return 0; }创建好的守护进程 系统也是有提供把进程守护进程化的方法的 #include unistd.hint daemon(int nochdir, int noclose);和上面模拟写的类似但传的参数不一样内部实现也若有不同 如果nochdir为零daemon()将调用进程的当前工作目录更改为根目录(“/”);否则当前工作目录保持不变。如果noclose为零daemon()将标准输入、标准输出和标准错误重定向到/dev/null;否则不会对这些文件描述符进行任何更改。 TCP通信协议过程 在tcp客户端和服务端连接采用三次握手也就是进行三次的报文交换SYN、SYNACK、ACK当三次握手完成后accept才会返回。connect一个系统调用只是发起了第一次握手三次握手的本质是建立共识 1. connect和accept都会阻塞式的等待三次握手的完成 2. 三次握手是建立链接前必须做的 在tcp客户端和服务端断开链接采用一次close关闭客户端-服务器通信信道对应着两次挥手发送FINACK报文所以两次close关闭-服务器客户端通信信道对应着四次挥手因为是全双工通信所以两方都需要要关闭信道 所以tcp建立链接需要三次握手断开链接需要四次挥手 本章完。预知后事如何暂听下回分解。 如果有任何问题欢迎讨论哈 如果觉得这篇文章对你有所帮助的话点点赞吧 持续更新大量计算机网络细致内容早关注不迷路。 ​
http://www.hkea.cn/news/14259786/

相关文章:

  • 梧州做网站建设网站建设和后台空间管理关系
  • 汕头做网站公司网站设计编辑
  • frontpage网站建设论文wordpress 显示小工具栏
  • 台州建设网站开发手机app难吗
  • 做不锈钢管网站岳阳卖房网站
  • 上海市交通建设工程安全质量监督站网站网站图片是用什么软件做的
  • 大沥网站制作外贸推广软件
  • 2008iis网站建设淮安软件园有做网站的吗
  • 建设部网站怎么查询相关专业代运营电商公司排行榜
  • 档案网站建设现状分析网站建设公司程序
  • 曲靖网站设计公司品牌营销的定义
  • 定制类做网站多少钱WORDPRESS导购主题:WYZDG
  • 成都企业网站设计制作php网站如何导入数据库
  • 网站开发 售后服务协议网站开发服务
  • 西安网站建设模板企业邮箱是qq邮箱吗
  • 网站 未备案 支付宝WordPress怎么找主题
  • 企业网站flashasp网站制作免费模板下载
  • 鄂尔多斯市网站建设单页网站订单系统怎么改邮箱
  • 国外建设网站用的是什么软件杭州建立网站
  • ui自学网站免费咨询律师要收费
  • 网站开发 怎样做费用结算福州网站建设案例
  • 网站优化检测wordpress时区设置
  • 单位网站制作湖南响应式网站哪里有
  • 下饶网站建设推广企业网站域名
  • 企业网站建设方案 ppt石景山做网站公司
  • 出口外贸营销网站小米手机的网站架构
  • 网站制作呼和浩特电销外包团队在哪找
  • 有做浏览单的网站网络广告商
  • 会展网站建设的步骤万网域名查询官网
  • 上海知名建站公司电子商务网站开发技术路线