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

做网站图片多大WordPress功能文件

做网站图片多大,WordPress功能文件,台州网页设计招聘,海拉尔建设局网站认识端口号 我们知道在网络数据传输的时候#xff0c;在IP数据包头部有两个IP地址#xff0c;分别叫做源IP地址和目的IP地址。IP地址是帮助我们在网络中确定最终发送的主机#xff0c;但是实际上数据应该发送到主机上指定的进程上的#xff0c;所以我们不仅要确定主机在IP数据包头部有两个IP地址分别叫做源IP地址和目的IP地址。IP地址是帮助我们在网络中确定最终发送的主机但是实际上数据应该发送到主机上指定的进程上的所以我们不仅要确定主机还要确定主机上的指定进程。而标识该进程的就是通过端口号。所以IP端口号port就能标识互联网中唯一的一个进程。 端口号是一个2字节16位的整数。端口号用来标识一个进程, 告诉操作系统, 当前的这个数据要交给哪一个进程来处理。IP地址 端口号能够标识网络上的某一台主机的某一个进程。一个端口号只能被一个进程占用。 端口号和进程pid  进程pid同样也是可以表示进程的唯一性但是为什么网络通信还需要新引入一个端口号来标识进程呢 并不是每一个进程都会进行网络通信所以有端口号的则表明需要进行网络通信。进程模块采用pid网络通信模块采用端口号port进行解耦。提高可维护性与扩展性。 一个进程可以绑定多个端口号创建多个socket套接字; 但是一个端口号不能被多个进程绑定端口号具有唯一性。   认识传输层协议 传输层有两个最常见的协议就是传输控制协议TCP和用户数据报协议UDP。 TCP协议是一种面向连接的协议它提供了可靠的、有序的数据传输是Internet上最常见的传输层协议。面向字节流传输。 UDP协议则是一种无连接的协议它不提供可靠的数据传输但具有低延迟和高效率的特点适用于需要实时性要求较高的应用场景如实时音视频传输等。面相数据报传输。 网络字节序 不同的主机大小端存储方式是不同的。内存和磁盘文件中的数据有大小端的区分网络数据流同样有大端小端之分而我们进行网络通信的时候就需要将大小端确定这样接收到的消息才是正确的顺序。 发送主机通常将发送缓冲区中的数据按内存地址从低到高的顺序发出;接收主机把从网络上接到的字节依次保存在接收缓冲区中,也是按内存地址从低到高的顺序保存;因此,网络数据流的地址应这样规定:先发出的数据是低地址,后发出的数据是高地址TCP/IP协议规定,网络数据流应采用大端字节序,即低地址高字节.不管这台主机是大端机还是小端机, 都会按照这个TCP/IP规定的网络字节序来发送/接收数据。如果当前发送主机是小端, 就需要先将数据转成大端; 否则就忽略, 直接发送即可 一般 在网络通信时会采用以上的库函数来进行网络字节序和主机字节序的转换。 套接字的认识 socket套接字API // 创建 socket 文件描述符 (TCP/UDP, 客户端 服务器) int socket(int domain, int type, int protocol);// 绑定端口号 (TCP/UDP, 服务器) int bind(int socket, const struct sockaddr *address,socklen_t address_len);// 开始监听socket (TCP, 服务器) int listen(int socket, int backlog);// 接收请求 (TCP, 服务器) int accept(int socket, struct sockaddr* address,socklen_t* address_len);// 建立连接 (TCP, 客户端) int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen); sockaddr结构 sockaddr是一个通用的套接字地址结构体在网络编程中用于表示套接字的地址信息。 struct sockaddr { unsigned short sa_family; // 地址族 char sa_data[14]; // 地址信息 }; 该结构体的产生其实就是为了统一各种不同的网络协议的地址格式是一个通用的地址类型。以便在不同函数接口中的参数能够统一 。在实际的网络通信中我们一般都是采用sockaddr_in结构体来存储套接字信息。 struct sockaddr_in { short int sin_family; // 地址族标识套接字所使用的网络协议类型unsigned short int sin_port; // 端口号 struct in_addr sin_addr; // IP地址 unsigned char sin_zero[8]; // 保留的空字节用于让sockaddr与sockaddr_in两个数据结构保持大小相同 }; udp网络程序多线程 thread_pool.h #pragma once#include iostream #include queue #include thread #include functional #include mutex #include vector #include unistd.h #include condition_variableusing namespace std; using namespace placeholders;#define numdefault 5template class T class thread_pool {thread_pool(const thread_pool)delete;thread_pool operator(const thread_pool)delete;public:static thread_pool* get_instance() // 单例{if(_instancenullptr)_instance new thread_pool();return _instance;}void task_execution(const string args) // 多个线程开始任务执行{while (1){T t;//调用默认构造{//共享代码段unique_lockmutex ul(_mtx);while (_qt.empty()) // 无任务就等待{cond.wait(ul); // 等待期间会解锁,多线程会再等待队列中阻塞等待成功会上锁}t _qt.front();_qt.pop();}// 处理任务coutargs: ;t();//执行bind好的函数sleep(1);}}void push(const T t)//传任务{unique_lockmutex ul(_mtx);_qt.push(t);cond.notify_one();//有任务则条件满足}~thread_pool()//{for (int i 0; i _num; i) // Cthread使用线程不join的话程序会崩溃{_vt[i].join();}}private:thread_pool(int num numdefault)//构造函数私有: _num(num), _vt(num){for (int i 0; i _num; i){string name thread_;name to_string(i 1);// 移动赋值线程不支持左值拷贝_vt[i] thread(bind(thread_poolT::task_execution, this,_1), name);//bind其实与function功能一样不过可以提前确定参数}}int _num; // 线程数目queueT _qt; // 任务管理vectorthread _vt; // 管理线程mutex _mtx; // 锁condition_variable cond; // 条件变量任务为空等待static thread_pool* _instance; }; templateclass T thread_poolT* thread_poolT::_instance nullptr;//单例 udpserver.h #pragma once #include iostream #include string #include memory #include sys/types.h #include sys/socket.h #include netinet/in.h #include arpa/inet.h #include cerrno #include cstring #include functional #include thread_pool.h using namespace std;#define default_size 1024 using Func functionstring(string); // 该类型下创建的对象就当做参数string返回值string的函数使用 using task_t functionvoid(); // 该类型下创建的对象就当做无参无返回值的函数使用,可以衔接bind修饰的函数将参数确定化class Inet_addr { public:Inet_addr() {}Inet_addr(const struct sockaddr_in clients): _si(clients), _ip(inet_ntoa(clients.sin_addr)), _port(ntohs(clients.sin_port)){}void print_client_info(const char *buffer){cout [port: _port ip: _ip ];cout client says: buffer endl;}bool operator(const Inet_addr com){return _ip com._ip _port com._port;}const struct sockaddr_in addr(){return _si;}const string ip(){return _ip;}const in_port_t port(){return _port;}~Inet_addr(){}private:struct sockaddr_in _si;string _ip;in_port_t _port; };class udp_server {public:udp_server(uint16_t port, Func f): _port(port), _func(f){}void init(){// 1.创建套接字本质就是创建文件细节_sockfd socket(AF_INET, SOCK_DGRAM, 0);if (_sockfd 0){exit(-1);}// 2.绑定套接字struct sockaddr_in local;bzero(local, sizeof(local)); // 全部初始化为0local.sin_family AF_INET; // socket inet(ip) 协议家族,绑定网络通信的信息local.sin_port htons(_port); // 将主机端口号序列转成网络local.sin_addr.s_addr INADDR_ANY; // 任意ip地址// local.sin_addr.s_addr inet_addr(_ip.c_str()); // 转成网络序列的四字节ipint n ::bind(_sockfd, (sockaddr *)local, sizeof(local));if (n -1){exit(-1);}// 单例的方式创建多线程thread_pooltask_t::get_instance();}void myfunc(const char *tmp) // 子线程执行的函数任务任务就是负责接收消息并发送出去{unique_lockmutex ul(_mtx);// 服务端接收消息后是将消息转发给所有的客户端for (auto ia : _vipport) // 遍历所有的客户端并依次发送{sendto(_sockfd, tmp, strlen(tmp), 0, (sockaddr *)ia.addr(), sizeof(ia.addr()));}}void start()//{while (1){// 客户端的主线程可以一直的收消息将服务端发送的消息交给创建的线程进行转发处理char buffer[default_size];struct sockaddr_in clients; // 是一个输入输出型参数接收消息以后会存入发消息的主机信息socklen_t len sizeof(clients);ssize_t n recvfrom(_sockfd, buffer, sizeof(buffer) - 1, 0, (sockaddr *)clients, len); // 收消息// 将所有不同的客户端主机信息都插入进容器以便服务端可以将信息发送给所有的客户端Inet_addr ia(clients);int i 0;for (i 0; i _vipport.size(); i) // 遍历查找是否是同一个用户发来的消息{if (_vipport[i] ia)break;}if (i _vipport.size())_vipport.push_back(ia);if (n 0){// 只有主线程才会执行start函数里的内容将服务器里的任务都压入线程池相关容器中buffer[n] 0;ia.print_client_info(buffer); // 打印用户端发送方的相关ip端口信息// 将任务压入进程池的任务管理容器中在等待队列中的线程会自动响应并处理task_t task std::bind(udp_server::myfunc, this, buffer); // 其实就是调用回调函数(bind可以固定参数)thread_pooltask_t::get_instance()-push(task);//不采用线程池的方式而是进行任务解析功能的代码// string messages _func(buffer); // 对服务器发送的消息进行处理然后再将处理结果发回去// sendto(_sockfd, messages.c_str(), messages.size(), 0, (sockaddr *)clients, len);}}}~udp_server() {}private:uint16_t _port;int _sockfd;Func _func; // 回调就相当于函数指针mutex _mtx; // 锁vectorInet_addr _vipport; // 存放所有客户端的ip和端口 };udpserver.cpp #include udpserv.hstring command(string message)//服务器对命令的解析 {FILE* fp popen(message.c_str(),r);//会将命令的结果回显到文件//popen的功能//1.创建管道父进程可以通过该管道向子进程发送输入指令同时也可以从该管道接收子进程执行命令的输出结果文件。//2.创建子进程子进程程序替换执行参数一的命令if(fpnullptr){return popen error!!!;}char buffer[default_size];string ret;while(1){char* sfgets(buffer,sizeof(buffer)-1,fp);//采用重写缓冲区的形式从文件中读取每一行数据if(!s) break;else retbuffer;}return ret.empty()?not find,please continue:ret;pclose(fp); }int main(int argc, char *argv[]) {if (argc ! 2){cout 格式错误\n正确格式: argv[0] port endl;}uint16_t port atoi(argv[1]);unique_ptrudp_server user(new udp_server(port,command)); // 自动析构user-init();user-start();return 0; } udpclient.cpp #include udpserv.h// 客户端不应该写成一发一收的形式如果在服务器多转发数据的时候时客户端只有发完消息以后才能收到消息 // 所以为客户端创建多线程形式一个负责专门发消息一个负责专门收消息void reciever(const u_int16_t sockfd)//收数据的线程 {while (1){// 收消息char buffer[default_size];struct sockaddr_in other; // 是一个输入输出型参数接收消息以后会存入发消息的主机信息socklen_t len sizeof(other);ssize_t m recvfrom(sockfd, buffer, sizeof(buffer) - 1, 0, (sockaddr *)other, len); // 收消息(来自于服务端)Inet_addr tmp(other);if (m 0){buffer[m] 0;tmp.print_client_info(buffer); // 打印发送方的相关ip端口信息}} } int main(int argc, char *argv[]) {if (argc ! 3){cout 格式错误\n正确格式: argv[0] ip port endl;}string ip argv[1];uint16_t port atoi(argv[2]);// 1.创建套接字本质就是创建文件细节u_int16_t sockfd socket(AF_INET, SOCK_DGRAM, 0);if (sockfd 0){lg.Log_infom(Fatal, 创建套接字失败: sockfd%d,%s, sockfd, strerror(errno));exit(-1);}lg.Log_infom(Fatal, 创建套接字成功: sockfd%d, sockfd);// 不需要显式bind绑定客户端发送消息的时候会自动绑定随机端口与当前ip// 服务端套接字信息配置struct sockaddr_in server;server.sin_family AF_INET; // socket inet(ip) 协议家族,绑定网络通信的信息server.sin_port htons(port); // 将主机端口号转成网络server.sin_addr.s_addr inet_addr(ip.c_str()); // 转成网络序列的四字节ip// 创建收消息的线程执行reciev方法thread reciev(reciever, sockfd);while (1){string info;//cout please enter:;getline(cin, info);ssize_t n sendto(sockfd, info.c_str(), info.size(), 0, (sockaddr *)server, sizeof(server));// 发消息给server服务端此时会绑定好相关套接字信息if(n0) cout发送消息失败endl;}reciev.join();return 0; } tcp网络程序多线程 Log.h打印日志信息 #pragma once #include iostream #include time.h #include map #include stdarg.h #include sys/types.h #include sys/stat.h #include sys/stat.h #include sys/types.h #include unistd.h #include fcntl.h using namespace std;enum // 可以设置日志等级 {Debug,Info,Warning,Error,Fatal }; enum // 打印方式 {Screen,onlyfile,classifyfile }; const string logdir log; // 目录文件 class Log { public:Log(){levermap[Debug] Debug;levermap[Info] Info;levermap[Warning] Warning;levermap[Error] Error;levermap[Fatal] Fatal;}void exchange(string s, tm *cur_time) // 时间戳转换成标准时间{s to_string(cur_time-tm_year 1900) / to_string(cur_time-tm_mon) / to_string(cur_time-tm_mday) - to_string(cur_time-tm_hour) : to_string(cur_time-tm_min) : to_string(cur_time-tm_sec);}void write_way(const string filename, const string loginfo) // 文件打印{mkdir(logdir.c_str(), 0777); // 创建目录并在指定目录下打印int fd open(filename.c_str(), O_WRONLY | O_APPEND | O_CREAT, 0666);if (fd -1)cout 文件打开失败 endl;write(fd, loginfo.c_str(), loginfo.size());close(fd);}void write_log(int lever, const string loginfo) // 日志写入位置{string tmp logdir / log.;switch (style){case 0: // 显示器打印cout loginfo;break;case 1: // log.txt里打印write_way(tmp txt, loginfo);break;case 2: // 分类到各自对应的文件里打印write_way(tmp levermap[lever], loginfo);break;default:break;}}void enable(int sty){style sty;}void Log_infom(int lever, const char *format, ...) // 格式formats{char tmp[1024];va_list args; // 可变参数部分的起始地址va_start(args, format); // 初始化通过format确定可变参数个数vsnprintf(tmp, sizeof(tmp), format, args); // 将数据写到tmp中va_end(args); //time_t t time(nullptr); // 得到当前的时间戳tm *cur_time localtime(t); // 传入时间戳string s;exchange(s, cur_time); // 转换成具体的时间string loginfo;loginfo loginfo tmp [ levermap[lever] ] [ s ] \n;write_log(lever, loginfo);}~Log(){}private:mapint, string levermap;int style 0; // 默认往显示器中打印int lever Debug; }; Log lg; tcp_server.h #pragma once #include inet.hpp #include Log.h #include thread_pool.h #include mapclass thread_data; // 提前声明 #define default_backlog 5 // 全连接队列 using task_t functionvoid(); // 包装器无参无返回值 using func_t functionvoid(thread_data);class thread_data // 线程对应的套接字描述符 { public:int _sockfd;Inet_addr _inet;thread_data(int sockfd, Inet_addr tmp) : _sockfd(sockfd), _inet(tmp){}~thread_data(){// close(_sockfd);不能在这里关闭因为线程的生命周期与thread_data对象不同步} };class tcp_server { public:tcp_server(uint16_t port): _port(port){}void inite(){// 1.创建套接字_listen_sockfd socket(AF_INET, SOCK_STREAM, 0);if (_listen_sockfd -1){lg.Log_infom(Fatal, 创建套接字失败error:%d,strerrno:%s,_listen_sockfd %d, errno, strerror(errno), _listen_sockfd);exit(-1);}lg.Log_infom(Debug, 创建套接字成功,sockfd %d, _listen_sockfd);// 解决一些服务端绑定失败无法重启的问题int opt 1;setsockopt(_listen_sockfd, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, opt, sizeof(opt));// 2.绑定网络信息struct sockaddr_in local;local.sin_family AF_INET;local.sin_addr.s_addr INADDR_ANY; // 宏值就是0local.sin_port htons(_port); // 端口号没绑好就会出错int n ::bind(_listen_sockfd, (sockaddr *)local, sizeof(local));if (n ! 0){lg.Log_infom(Fatal, 绑定网络信息失败error:%d,strerrno:%s,bind_ret %d, errno, strerror(errno), n);exit(-1);}lg.Log_infom(Debug, 绑定网络信息成功,bind_ret %d, n);// 3.客户端发起连接服务器等待连接将套接字设置为监听状态n listen(_listen_sockfd, default_backlog);if (n -1){lg.Log_infom(Fatal, 监听套接字失败error:%d,strerrno:%s,listensocket %d, errno, strerror(errno), n);exit(-1);}lg.Log_infom(Debug, 监听套接字成功,bind_ret %d, n);// 创建线程池thread_pooltask_t::get_instance();}// void Service(int sockfd) // 用于v1和v2// {// while (1)// {// char buffer[1024] {0};// int n read(sockfd, buffer, sizeof(buffer) - 1);// if (n 0)// {// buffer[n] 0;// lg.Log_infom(Debug, server recieve info:%s, buffer);// }// else if (n 0) // 读到文件末尾// {// lg.Log_infom(Info, 数据已经全部读取完毕...);// break;// }// else// {// lg.Log_infom(Error, 数据读取失败);// break;// }// write(sockfd, buffer, strlen(buffer)); // sizeof此时大小还是1024// cout send info: buffer endl;// }// }// void Service(thread_data tmp) // 重载(v3多线程使用)// {// while (1)// {// char buffer[1024] {0};// int n read(tmp._sockfd, buffer, sizeof(buffer) - 1);// if (n 0)// {// buffer[n] 0;// tmp._inet.print_client_info(buffer);// }// else if (n 0) // 读到文件末尾// {// lg.Log_infom(Info, 数据已经全部读取完毕...);// break;// }// else// {// lg.Log_infom(Error, 数据读取失败);// break;// }// write(tmp._sockfd, buffer, strlen(buffer)); // sizeof此时大小还是1024// cout send info: buffer endl;// }// }// void handler(thread_data tmp)// {// Service(tmp); // 内部是while循环在v4线程池是将线程与用户一一分配了当客户端线程个数就无法输入// close(tmp._sockfd);// }void start(){while (1){// 4.服务端获取客户端连接提供断线重连的方式struct sockaddr_in client;socklen_t len sizeof(client);int sockfd accept(_listen_sockfd, (sockaddr *)client, len); // 每连接一次都会返回一个新的sockfd负责接下来的通信if (sockfd 0){lg.Log_infom(Warning, 服务端获取连接失败error:%d,strerrno:%s,newsockedt %d, errno, strerror(errno), sockfd);continue; // 获取连接失败继续获取}lg.Log_infom(Debug, 服务端获取连接成功,newsocket %d, sockfd);***v1:一般模式// 5.提供服务进行通信// Service(sockfd);// 关闭文件// close(sockfd);***v2:创建子进程父进程进行获取不同客户端的连接子进程进行通信(此时就可以多客户端通信)// 此时有3、4号文件描述符(父子共享)// signal(SIGCHLD,SIG_IGN);//在linux环境中,对该信号进行忽略则表明在子进程退出的时候就会自动释放资源// pid_t id fork(); // 创建子进程// if (id -1)// {// lg.Log_infom(Error, 创建子进程失败,fork_ret%d, id);// close(sockfd);// continue;// }// a.创建孙子进程的方式// else if (id 0) // 子进程// {// close(_listen_sockfd);// if (fork() 0) // 执行完毕后退出当前进程子进程// exit(0);// // 接下来就是孙子进程所执行的代码// Service(sockfd); // 孙子进程的父进程已经退出了所以被OS领养回收资源// exit(0);// }// else if (id 0)// {// close(sockfd);// // 等待子进程退出// pid_t ret waitpid(id, nullptr, 0);// if (ret id)// ;// }// b.采用父进程不等待的方式,而是信号的方式// else if (id 0) // 子进程// {// close(_listen_sockfd);// Service(sockfd); // 孙子进程的父进程已经退出了所以被OS领养回收资源// exit(0);// }// else if (id 0)// {// close(sockfd);// }***v3创建多线程(父进程不断地循环等待连接每个线程取决于客户端申请连接执行自己的任务)// thread_data tmp(sockfd,Inet_addr(client));//第二个参数存放发送者的套接字信息// thread t(std::bind(tcp_server::handler,this,placeholders::_1),tmp);// //此时父进程执行后续代码可能会再进行一次accept获取连接那么sockfd的值可能会改变// t.detach();//线程分离父进程不用等待回收***v4线程池提前将线程创建好,主线程进行任务的接收并存入线程池的任务栏子线程进行任务处理// thread_data tmp(sockfd, Inet_addr(client)); // 第一个参数是每个线程对应的sockfd,第二个参数存放发送者的套接字信息// task_t t std::bind(tcp_server::handler, this, tmp);// thread_pooltask_t::get_instance()-push(t); // 将任务压入进程池的任务栏***v4.2线程池执行任务thread_data tmp(sockfd, Inet_addr(client)); // 第一个参数是每个线程对应的sockfd,第二个参数存放发送者的套接字信息task_t t std::bind(tcp_server::routine, this, tmp);thread_pooltask_t::get_instance()-push(t); // 将任务压入进程池的任务栏}}void registr(string s, func_t f) // 将任务提前登记{_mapfunc[s] f;}void routine(thread_data tmp) // 线程接收客户端发送的任务种类并进行处理代替handler下的service功能{//读取任务种类char buffer[1024] {0};int n read(tmp._sockfd, buffer, sizeof(buffer) - 1);string s;if (n 0){buffer[n] 0;sbuffer;}else if (n 0) // 读到文件末尾{lg.Log_infom(Info, 数据已经全部读取完毕...);}else{lg.Log_infom(Error, 数据读取失败);}//子进程判断任务并执行if (sping)_mapfunc[s](tmp);else if(stranslate)_mapfunc[s](tmp);else if(stransform)_mapfunc[s](tmp);else_mapfunc[default_func](tmp);close(tmp._sockfd);//线程执行完毕就关闭}~tcp_server(){}private:uint16_t _port;int _listen_sockfd;mapstring, func_t _mapfunc; }; tcpserver.cpp #include fstream #include algorithm #include ctype.h #include tcp_server.hppvoid Ping(thread_data tmp) {tmp._inet.print_client_info(ping);char buffer[1024] {0};int n read(tmp._sockfd, buffer, sizeof(buffer) - 1);if (n 0){buffer[n] 0;lg.Log_infom(Debug, server recieve info:%s, buffer);}else if (n 0) // 读到文件末尾{lg.Log_infom(Info, 数据已经全部读取完毕...);}else{lg.Log_infom(Error, 数据读取失败);}write(tmp._sockfd, buffer, strlen(buffer)); // sizeof此时大小还是1024cout send info: buffer endl; } class dict { public:mapstring, string _dicts;dict(){// 直接将txt文本文件中的单词全部录入到dicts中std::ifstream file(./test.txt); // 打开文件vectorstring lines;string line;if (file.is_open())// 检查文件是否成功打开{while (std::getline(file, line)) // 按行读取文件内容{lines.push_back(line);}file.close(); // 关闭文件}else{std::cerr 无法打开文件 std::endl;}// 将lines中的数据按照key-val的形式填入for (auto s : lines){string tmp s;int i s.find( );_dicts[tmp.substr(0, i)] tmp.substr(i 1);}}const string operator[](const string tmp){if (_dicts.find(tmp) _dicts.end())return 暂时还未录入该数据到词典中;return _dicts[tmp];}~dict(){} };dict dictionary;//放到外面就不用每次都重新初始化 void Translate(thread_data tmp) { tmp._inet.print_client_info(translate);// 读取任务char buffer[1024] {0};int n read(tmp._sockfd, buffer, sizeof(buffer) - 1);string s;if (n 0){buffer[n] 0;s buffer;}string chines dictionary[s];// 返回任务结果write(tmp._sockfd, chines.c_str(), chines.size()); // sizeof此时大小还是1024cout send info: chines endl; }void Transform(thread_data tmp) {tmp._inet.print_client_info(transform);// 读取任务char buffer[1024] {0};int n read(tmp._sockfd, buffer, sizeof(buffer) - 1);string s;if (n 0){buffer[n] 0;s buffer;}std::transform(s.begin(), s.end(), s.begin(), [](char c) - char{ return toupper(c); });// 返回任务结果write(tmp._sockfd, s.c_str(), s.size()); // sizeof此时大小还是1024cout send info: s endl; } void default_func(thread_data tmp) {tmp._inet.print_client_info(default);// 读取任务不处理char buffer[1024] {0};read(tmp._sockfd, buffer, sizeof(buffer) - 1);// 返回任务结果string s 目前没有该类型任务请重新输入正确的任务类型,例如1.ping 2.translate 3.transform;write(tmp._sockfd, s.c_str(), s.size());cout send info: s endl; }int main(int argc, char *argv[]) {if (argc ! 2){cout 格式错误,正确格式: argv[0] port endl;}uint16_t port atoi(argv[1]);unique_ptrtcp_server user(new tcp_server(port)); // 自动析构// 登记消息对应的方法user-registr(ping, Ping);user-registr(translate, Translate);user-registr(transform, Transform);user-registr(default_func, default_func);user-inite();user-start();return 0; } tcpclient.cpp设置断线重连 #include tcp_server.hpp#define default_count 5int main(int argc, char *argv[]) {if (argc ! 3){cout 格式错误\n正确格式: argv[0] ip port endl;}string ip argv[1];uint16_t port atoi(argv[2]);int count 1;while (count default_count){// 1.创建套接字int sockfd socket(AF_INET, SOCK_STREAM, 0);if (sockfd -1){lg.Log_infom(Fatal, 创建套接字失败error:%d,strerrno:%s,sockfd %d, errno, strerror(errno), sockfd);exit(-1);}lg.Log_infom(Debug, 创建套接字成功,sockfd %d, sockfd);// 需要绑定网络信息但是不用显式绑定一般在通信的时候就自动绑定上了// tcp在发起连接的时候就被os绑定好了// 2.建立连接struct sockaddr_in server;memset(server, 0, sizeof(server));server.sin_family AF_INET; // socket inet(ip) 协议家族,绑定网络通信的信息server.sin_port htons(port); // 将主机端口号转成网络// server.sin_addr.s_addr inet_addr(ip.c_str()); // 转成网络序列的四字节ipinet_pton(AF_INET, ip.c_str(), server.sin_addr); // 转成网络序列的四字节ipint n connect(sockfd, (sockaddr *)server, sizeof(server)); // 自动bindstring tmp; // 先读取任务类型if (n -1){lg.Log_infom(Fatal, 客户端连接失败...连接次数: %d, count);sleep(1);goto END; // 该段代码段之间不能创建对象}lg.Log_infom(Error, 客户端建立连接成功,connect_ret: %d, n);count 1;// 3.数据传输cout please enter style: ;getline(cin, tmp);write(sockfd, tmp.c_str(), tmp.size()); // 对端已经关闭写端继续写的话就会触发异常while (1){string s;cout please enter: ;getline(cin, s);int m write(sockfd, s.c_str(), s.size()); // 对端已经关闭写端继续写的话就会触发异常if (m 0) // 发送成功{char buffer[1024] {0};int n read(sockfd, buffer, sizeof(buffer) - 1);if (n 0){buffer[n] 0;lg.Log_infom(Debug, client recieve info:%s, buffer);break;}else if (n 0) // 读到文件末尾{lg.Log_infom(Info, 数据已经全部读取完毕,即服务端关闭了文件描述符sockfd...);break;}else{lg.Log_infom(Error, 数据读取失败);break;}}else{cout 写数据失败 endl;break;}}END:close(sockfd);}return 0; } 守护进程精灵进程 首先我们要知道实际上我们的网络服务并不能在bash中以前台进程的方式运行而是以守护进程的方式在后台一直运行着不退出。 守护进程的特点 在系统后台运行守护进程在后台运行不与控制台交互也不会在终端上显示任何输出所以不受任何终端控制自己是一个独立的会话守护进程不隶属于任何bash会话自己自成进程组自成会话。守护进程一般不会退出就算系统退出重新登录Linux系统守护进程依旧不会退出只有强制将守护进程kill -9掉才能退出进程。 认识进程组会话 当我们的其中一个中断执行sleep 120命令之后在另一个中断查看sleep进程时最上面的PGID就是进程组IDSID就是会话IDTTY就是指当前进程打开的终端设备。 可以发现我们的进程组ID等于当前进程ID而进程的会话ID等于当前进程的父进程IDbash。 我们登录Linux时操作系统都会提供一个bash和一个终端给用户提供命令解析服务。其实这就是一个会话。而我们在命令行中启动的所有进程都是隶属于当前会话的所以进程组也是属于会话的。而且会话ID其实就是bash进程的ID。因为bash提供的正是命令解析的服务 当我们查看我们的bash进程的时候会发现bash进程的PIDPGIDSID都是相等的所以bash进程是自成进程组自成会话。所以具象化的认识就是如下 其实可以通过创建一批进程来确定进程组ID 该方式创建的进程属于同一个进程组进程组ID相同 该方式创建的进程属于三个不同进程组进程组ID不同 我们可以知道同一个会话中不管运行多少个进程组会话ID都是bash 。而进程组ID取决于进程的运行如果是兄弟进程同时运行的方式则进程组ID就是最先运行的那个进程PID但如果采用后台进程的方式创建多个进程的话那么自己的进程组ID就等于自己进程的PID。还有一点就是任何时刻一个会话内部可以存在多个进程组但是只有一个进程组在前台。 守护进程实现 想要实现守护进程首先就要创建一个会话 pid_t setsid(void);//创建一个新会话并让自己成为会话的话首进程 但是调用setsid创建新会话是有条件的代用setsid的进程不能是一个进程组组长而进程组组长是会话中创建进程组的第一个进程所以一个会话中可以有多个进程组组长。 所以我们的解决方式是创建子进程并让父进程退出子进程执行后续代码。此时我们父进程虽然退出了但进程组ID依旧是父进程的PID因为进程组ID是与会话 相关联的而不是与单个进程相关联的。只有当会话中的最后一个进程退出时会话和与之相关联的进程组才会结束。而且可以知道守护进程本就是孤儿进程。 void daemon(int is_change) {// 一个会话内部可以有多个进程组但默认任何时刻只有一个进程组在前台// 1.守护进程自己是一个独立的会话不隶属于任何一个bash会话。pid_t fi fork(); // 当父进程退出时进程组的组长不会改变仍然是原来的组长进程// 2.让自己不要成为组长关闭父进程守护进程也就是孤儿进程,其父进程是系统pid1if (fi 0)exit(0);// 3. // 返回新的会话即pidpgidsid条件是调用进程不能是进程组的组长pid_t si setsid();if (si -1){cout 调用该函数失败失败,不能是组长调用该进程 endl;exit(-1);}// 4.是否将当前工作目录更改为根目录if (is_change)chdir(/);// 5.守护进程不需要进行输入输出,将输入输出到/dev/null下自动丢弃int fd open(/dev/null, O_RDWR);if (fd 0){// 重定向dup2(fd, 0);dup2(fd, 1);dup2(fd, 2);close(fd);} }
http://www.ho-use.cn/article/10817124.html

相关文章:

  • 西部数码网站管理助手破解版湖南电商网站建设
  • 昆山做网站好的wordpress 语录小程序
  • 如何做网站的信息分类优秀建筑设计案例
  • 网站开发是固定资产吗优秀网站建设服务
  • 湛江做网站的公司24小时国内新闻大事
  • 网站排名提升易下拉教程wordpress用户页
  • 网站运行环境配置昌吉做58网站的
  • 南昌网站维护制作如何做网站写手
  • 投资担保网站建设优化关键词的方法有哪些
  • 衡阳房产网站建设中高风险地区最新名单
  • 网站建设会犯法吗wordpress原生评论
  • 电子商务网站如何推广中山哪里网站建设
  • 最好看免费观看高清大全新员工怎样优化推广
  • 长春做网站多少钱个人响应式网站建设
  • 网站备案 哪个省最松营销网站建设的规则
  • 西安金融网站建设专业网站建设空间
  • 谷歌认证合作伙伴网站建设东莞企业建站程序
  • 重庆微信网站建设多少钱音乐网站制作课程报告
  • 山东网站建设运行工资网站建设买了服务器后怎么做
  • 网站布局的三种基本方法网站引导页动态效果怎么做的
  • 建设公司网站法律声明网站正在建设中怎么办
  • 刚成立公司如何做网站做网站可以用电脑当服务器吗
  • 酒店 公司 安徽 网站建设企业网络营销分析
  • 阿里云服务器做网站怎样制作自己的app
  • 大型门户网站核心技术网站建设哪家合适
  • 专题页网站wordpress展开 折叠功能
  • 泉州网站建设哪里优惠首钢建设一公司网站
  • 福田网站建设公司哪家性价比高网站建设知识点的总结
  • 工信部网站icp备案号学校网站建设报价单
  • 做哪种类型网站赚钱时尚女装网站模版