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

网站微信收款二维码怎么做做网站多少钱PageAdmin

网站微信收款二维码怎么做,做网站多少钱PageAdmin,wordpress阿里云推送,百度网盘网页登录入口前言 前面我们学习socket的udp通信#xff0c;了解到了socket的概念与udp的实现方法#xff0c;今天我们来学习一下面向连接的tcp通信。 一、tcp套接字创建 UDP和TCP都是通过套接字#xff08;socket#xff09;来实现通信的#xff0c;因此TCP也得使用socket()接口创建…前言 前面我们学习socket的udp通信了解到了socket的概念与udp的实现方法今天我们来学习一下面向连接的tcp通信。 一、tcp套接字创建 UDP和TCP都是通过套接字socket来实现通信的因此TCP也得使用socket()接口创建套接字。 socket()    -创建套接字 参数domain代表协议家族输入AF_INET为IPv4协议该参数告诉操作系统如何解释后面的type和protocol参数参数type指定了套接字的类型即指定了套接字的通信方式和数据传输方式输入SOCK_STREAM面向字节流参数protocol代表所使用的具体协议输入0让系统自动选择合适的协议 二、填充网络信息并bind 创建好了基于tcp的IPv4套接字我们还需要填充本地网络信息知道了本地ip地址和端口号和socket创建的sockfd进行绑定后面就可以通过sockfd进行通信了。 如下是 IPv4 地址的结构体sockaddr_in 。 struct sockaddr_in {short int sin_family; // 地址族Address Family一般为 AF_INETunsigned short int sin_port; // 端口号Port使用网络字节顺序big-endianstruct in_addr sin_addr; // IPv4 地址unsigned char sin_zero[8]; // 未使用的填充字段通常设置为 0 };填充完毕就可以开始bind了。 bind()   -让socket信息与sockfd进行绑定 参数sockfd套接字文件描述符  传入之前创建的socket返回值参数addr创建好的sockaddr结构体的地址参数addrlen网络信息结构体的长度的长度 三、建立连接与监听 由于tcp是面向连接的因此客户端和服务器双方要进行数据通信必须要先建立连接。一般都是客户端去发起连接请求想让服务端为他进行服务。比如你想刷抖音那么你得打开抖音申请去刷抖音而不是说抖音舔着脸求你刷我虽然他也想要日活但是主动权还是在你手上的。 那服务端也需要去监听连接的到来方便为客户端服务因此有连接和监听两种状态。 connect()  建立连接 参数与bind一样  listen()  监听连接 参数sockfd套接字描述符参数backlog指定连接请求的最大排队数量即在队列中等待接受连接的最大数量。他只是用于控制等待连接队列的长度并不是服务器的最大并发连接数。返回值成功返回0 listen返回值不为0证明listen失败。  四、获取连接 客户端使用connect与服务端进行连接服务端listen将自己设置为监听状态代表能接受连接但是你只是说自己能接受并不会创建与客户端的连接。 正在的连接需要服务端既要listen进行监听又要accept进行获取连接。 accept()  从处于监听状态的套接字中接受一个传入的连接请求,并创建一个新的套接字来与客户端进行通信。 参数sockfd处于监听状态的套接字描述符参数addr创建好的sockaddr结构体的地址参数addrlen创建好的sockaddr结构体的长度的地址返回值返回一个sockfd使用返回的这个sockfd与客户端进行通信。 也就是说在tcp通信中是有两个sockfd的之前我们socket、bind、listen、accept使用的都是同一个sockfd但是链接已经完全建立好之后我们要与客户端进行通信需要使用accept返回的sockfd。 这就类似于在街边拉客的美容店张三在外面寻找客人带到美容店去消费进入美容店后张三就不再管你了而是让美容店里的员工对你进行服务张三转头又去拉客去了。 五、tcp通信的实现 有了这些预备知识我们就可以编写代码了具体代码如下注释写的比较详细 Comm.hpp   错误码 #pragma once//错误码 enum{Usage_Err 1,Socket_Err,Bind_Err,Listen_Err,Connect_Err, }; InetAddr.hpp  封装sockaddr_in结构体 #pragma once #includestring #includesys/types.h #includesys/socket.h #includenetinet/in.h #includearpa/inet.h using namespace std; class InetAddr { public:InetAddr(struct sockaddr_in peer):_addr(peer){_port ntohs(peer.sin_port); // ntohs网络转主机short// inet_ntoa 多线程下不安全 使用静态缓冲区来存储结果并返回指向这个静态缓冲区的指针// 每次调用都会覆盖这个静态缓冲区的内容// _ip inet_ntoa(peer.sin_addr); // inet_ntoa sin_addr转点分十进制字符串ip// 现在我们自己维护空间ipbuff让inet_ntop把数据写到ipbuff里 这样线程安全char ipbuff[64]; inet_ntop(AF_INET,peer.sin_addr,ipbuff,sizeof(ipbuff));_ip ipbuff;}string GetIp(){return _ip;}uint16_t GetPort(){return _port;}struct sockaddr_in GetAddr(){return _addr;}string PrintDebug(){string info _ip;info:;infoto_string(_port);return info;}~InetAddr(){}private:string _ip;uint16_t _port;struct sockaddr_in _addr; }; LockGuard.hpp  锁的守护者就是C11里的lock_guard #pragma once #include pthread.h// 不定义锁外部会传递锁 class Mutex { public:Mutex(pthread_mutex_t *lock): _lock(lock){}void Lock(){pthread_mutex_lock(_lock);}void UnLock(){pthread_mutex_unlock(_lock);}~Mutex(){}private:pthread_mutex_t *_lock; };class LockGuard { public:LockGuard(pthread_mutex_t *lock): _mutex(lock){_mutex.Lock();}~LockGuard(){_mutex.UnLock();} private:Mutex _mutex; }; Log.hpp  日志类  #pragma once#includeiostream #includecstdarg #includeunistd.h #includesys/stat.h #includesys/types.h using namespace std; enum{Debug 0,Info,Warning,Error,Fatal };enum{Screen 10,OneFile,ClassFile };string LevelToString(int level) {switch (level){case Debug:return Debug;case Info:return Info;case Warning:return Warning;case Error:return Error;case Fatal:return Fatal;default:return Unkonw; } }const int default_style Screen; const string default_filename Log.; const string logdir log;class Log { public:Log(int style default_style,string filename default_filename):_style(style),_filename(filename){if(_style ! Screen)mkdir(logdir.c_str(),0775);}//更改打印方式void Enable(int style){_style style;if(_style ! Screen)mkdir(logdir.c_str(),0775);}//时间戳转化为年月日时分秒string GetTime(){time_t currtime time(nullptr);struct tm* curr localtime(currtime);char time_buffer[128];snprintf(time_buffer,sizeof(time_buffer),%d-%d-%d %d:%d:%d,curr-tm_year1900,curr-tm_mon1,curr-tm_mday,curr-tm_hour,curr-tm_min,curr-tm_sec);return time_buffer;}//写入到文件中void WriteLogToOneFile(const string logname,const string message){FILE* fp fopen(logname.c_str(),a);if(fpnullptr){perror(fopen filed);exit(-1);}fprintf(fp, %s\n, message.c_str());fclose(fp);}//打印日志void WriteLogToClassFile(const string levelstr,const string message){string logname logdir;logname/;logname_filename;lognamelevelstr;WriteLogToOneFile(logname,message);}void WriteLog(const string levelstr,const string message){switch (_style) {case Screen:coutmessageendl;//打印到屏幕中break;case OneFile:WriteLogToClassFile(all,message);//给定all直接写到all里break;case ClassFile:WriteLogToClassFile(levelstr,message);//写入levelstr里break;default:break;}}//打印日志void LogMessage(int level,const char* format,...){char rightbuffer[1024];//处理消息va_list args; //va_list 是指针va_start(args,format);//初始化va_list对象format是最后一个确定的参数//现在args指向了可变参数部分vsnprintf(rightbuffer,sizeof(rightbuffer),format,args);//写入到leftbuffer中va_end(args);char leftbuffer[1024];//处理日志等级、pid、时间string levelstr LevelToString(level);string currtime GetTime();string idstr to_string(getpid());snprintf(leftbuffer,sizeof(leftbuffer),[%s][%s][%s],levelstr.c_str(),currtime.c_str(),idstr.c_str());string loginfo leftbuffer;loginforightbuffer;WriteLog(levelstr,loginfo);}//提供接口给运算符重载使用void _LogMessage(int level,char* rightbuffer){char leftbuffer[1024];string levelstr LevelToString(level);string currtime GetTime();string idstr to_string(getpid());snprintf(leftbuffer,sizeof(leftbuffer),[%s][%s][%s],levelstr.c_str(),currtime.c_str(),idstr.c_str());string messages leftbuffer;messagesrightbuffer;WriteLog(levelstr,messages);}//运算符重载void operator()(int level,const char* format,...){char rightbuffer[1024];va_list args; //va_list 是指针va_start(args,format);//初始化va_list对象format是最后一个确定的参数vsnprintf(rightbuffer,sizeof(rightbuffer),format,args);//写入到leftbuffer中va_end(args);_LogMessage(level,rightbuffer);}~Log() {} private:int _style;string _filename; };Log lg;class Conf { public:Conf(){lg.Enable(Screen); }~Conf(){} };Conf conf; nocopy.hpp   让服务器类继承nocopy达到不可拷贝的作用 #pragma onceclass nocopy { public:nocopy(){}nocopy(const nocopy n) delete;nocopy operator(const nocopy n) delete;~nocopy(){} }; Thread.hpp    Thread库封装 #pragma once#include iostream #include string #include functional #include pthread.h// 设计方的视角 //typedef std::functionvoid() func_t; namespace kky {templateclass T using func_t std::functionvoid(T);templateclass T class Thread { public:Thread(const std::string threadname, func_tT func, T data):_tid(0), _threadname(threadname), _isrunning(false), _func(func), _data(data){}// 不加static会有this指针无法调用pthread_creadtestatic void *ThreadRoutine(void *args) // 类内方法{// (void)args; // 仅仅是为了防止编译器有告警Thread *ts static_castThread *(args);ts-_func(ts-_data);return nullptr;}//运行线程bool Start(){int n pthread_create(_tid, nullptr, ThreadRoutine, this/*?*/);if(n 0) {_isrunning true;return true;}else return false;}//等待线程bool Join(){if(!_isrunning) return true;int n pthread_join(_tid, nullptr);if(n 0){_isrunning false;return true;}return false;}std::string ThreadName(){return _threadname;}bool IsRunning(){return _isrunning; }~Thread(){} private:pthread_t _tid;std::string _threadname;bool _isrunning;func_tT _func;T _data; }; } Threadpool.hpp  线程库的封装 #pragma once#include pthread.h #include vector #include functional #include queue #include Log.hpp #include Thread.hpp #include LockGuard.hpp using namespace std;namespace kky { static const int default_num 5;class ThreadData { public:ThreadData(string name): thread_name(name){}string thread_name; };template class T class ThreadPool { private:ThreadPool(int thread_num default_num): _thread_num(thread_num){pthread_mutex_init(_mutex, nullptr); // 初始化pthread_cond_init(_cond, nullptr);// 创建指定个数的线程for (int i 0; i _thread_num; i){string thread_name thread_;thread_name to_string(i 1);ThreadData td(thread_name); // ThreadData为线程数据类型ThreadThreadData t(thread_name, bind(ThreadPoolT::ThreadRun, this, placeholders::_1), td);_threads.emplace_back(t);lg(Info, %s 被创建..., thread_name.c_str()); // 写入}}ThreadPool(const ThreadPoolT tp) delete;const ThreadPoolT operator(const ThreadPoolT tp) delete;public:static ThreadPoolT *GetInstance(){if(instance nullptr) {LockGuard lockguard(sig_lock);if (instance nullptr){instance new ThreadPoolT();lg.LogMessage(Info, 创建单例成功...);}}return instance;}// 线程运行bool Start(){for (auto thread : _threads){thread.Start();lg.LogMessage(Info, %s 正在运行, thread.ThreadName().c_str());}}// 线程条件变量等待void ThreadWait(ThreadData td){lg.LogMessage(Debug, 没有任务,%s休眠了, td.thread_name.c_str());pthread_cond_wait(_cond, _mutex);}// 线程条件变量唤醒void ThreadWakeUp(){pthread_cond_signal(_cond);}// 执行任务void ThreadRun(ThreadData td){while (1){T t;// 取出任务{LockGuard lockguard(_mutex); // 代码块中自动加锁与解锁while (_q.empty()){ThreadWait(td);lg.LogMessage(Debug, 有任务了,%s去执行任务了, td.thread_name.c_str());}t _q.front();_q.pop();}t();// 处理任务 我们通过打印消息来模拟任务// couttendl;// lg.LogMessage(Debug, %s 计算结果为%d, td.thread_name.c_str(), t);}}// 将任务放到队列中void Push(const T in){{LockGuard lockguard(_mutex);_q.push(in);}lg.LogMessage(Debug, 任务push成功);ThreadWakeUp();}~ThreadPool(){pthread_mutex_destroy(_mutex); // 销毁pthread_cond_destroy(_cond);}// 进程等待void Wait(){for (auto thread : _threads){thread.Join();}}private:queueT _q;vectorThreadThreadData _threads;int _thread_num;pthread_mutex_t _mutex;pthread_cond_t _cond;static ThreadPoolT *instance;static pthread_mutex_t sig_lock; };template class T ThreadPoolT *ThreadPoolT::instance nullptr;templateclass T pthread_mutex_t ThreadPoolT::sig_lock PTHREAD_MUTEX_INITIALIZER; } TcpServer.hpp   服务端的封装 #pragma once #include iostream #include string #include cerrno #include cstring #include cstdlib #include unordered_map #include functional #include unistd.h #include sys/types.h #include sys/socket.h #include netinet/in.h #include arpa/inet.h #include sys/wait.h #include thread #include Log.hpp #include Comm.hpp #include nocopy.hpp #include InetAddr.hpp #include Threadpool.hppclass ThreadData; static const int default_backlog 5; using func_t functionvoid(ThreadData *); using task_t functionvoid(); using callback_t functionvoid(int sockfd, InetAddr addr);class ThreadData { public:ThreadData(int sock, struct sockaddr_in peer): _sockfd(sock), _addr(peer){}~ThreadData(){close(_sockfd);}public:int _sockfd;InetAddr _addr; };class TcpServer : public nocopy { public:TcpServer(uint16_t port): _port(port), _isrunning(false){}void HandlerRequest(ThreadData *td){Service1(td-_sockfd);delete td;}void Init(){// 1.创建套接字 得到文件描述符_listen_sockfd socket(AF_INET, SOCK_STREAM, 0); // SOCK_STREAM 代表TCP字节流if (_listen_sockfd 0){lg.LogMessage(Fatal, create socket error, \errno code: %d,error string: %s,errno, strerror(errno));exit(Socket_Err);}lg.LogMessage(Debug, create socket success, sockfd: %d, _listen_sockfd);// 固定写法解决一些少量bind失败的问题int opt 1;setsockopt(_listen_sockfd, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, opt, sizeof(opt));// 2.填充网络信息struct sockaddr_in local;memset(local, 0, sizeof(local));local.sin_family AF_INET;local.sin_port htons(_port);local.sin_addr.s_addr INADDR_ANY;// 3.bindint n bind(_listen_sockfd, (struct sockaddr *)local, sizeof(local));if (n ! 0){lg.LogMessage(Fatal, bind socket error, \errno code: %d,error string: %s,errno, strerror(errno));exit(Bind_Err);}lg.LogMessage(Debug, bind socket success, sockfd: %d, _listen_sockfd);// 4.设置监听状态TCP特有的if (listen(_listen_sockfd, default_backlog) ! 0){lg.LogMessage(Fatal, listen socket error, \errno code: %d,error string: %s,errno, strerror(errno));exit(Listen_Err);}lg.LogMessage(Debug, listen socket success, sockfd: %d, _listen_sockfd);kky::ThreadPooltask_t::GetInstance()-Start();funcs.insert(make_pair(defaultService,std::bind(TcpServer::DefaultService,this,placeholders::_1,placeholders::_2)));}// accept获取的sockfd是全双工的因此我们read和write都可以用这个sockfdvoid Service1(int sockfd){char buff[1024];while (true){ssize_t n read(sockfd, buff, sizeof(buff) - 1);if (n 0){buff[n] 0;cout client say# buff endl;string echo_string server echo# ;echo_string buff;write(sockfd, echo_string.c_str(), echo_string.size());}else if (n 0) // 表示对面关闭了连接{lg.LogMessage(Info, client quit...);break;}else{lg.LogMessage(Error, read socket error, \errno code: %d,error string: %s,errno, strerror(errno));break;}}}void Service2(int sockfd, InetAddr addr){char buff[1024];while (true){ssize_t n read(sockfd, buff, sizeof(buff) - 1);if (n 0){buff[n] 0;cout [ addr.PrintDebug() ]# buff endl;string echo_string server echo# ;echo_string buff;write(sockfd, echo_string.c_str(), echo_string.size());}else if (n 0) // 表示对面关闭了连接{lg.LogMessage(Info, client quit...);break;}else{lg.LogMessage(Error, read socket error, \errno code: %d,error string: %s,errno, strerror(errno));break;}}}void Start(){_isrunning true;// 忽略SIGCHLD信号那么子进程退出时内核会自动回收其资源并且不会产生僵尸进程// 与下面v3版本多线程一起使用如果不是V3版本这句代码无用signal(SIGCHLD, SIG_IGN);while (_isrunning){struct sockaddr_in peer;memset(peer, 0, sizeof(peer));socklen_t len sizeof(peer);// 5.获取连接int sockfd accept(_listen_sockfd, (struct sockaddr *)peer, len);if (sockfd 0){lg.LogMessage(Warning, accept socket error);continue;}lg.LogMessage(Debug, accept socket success,get a new sockfd: %d, sockfd);// 6.提供服务// 6.v1版本 只能一个为一个进程服务// Service1(sockfd);// close(sockfd);// v2 多进程 fork()孙子进程版本// pid_t id fork();// if(id0)// {// close(sockfd);// continue;// }// else if(id 0)// {// //子进程不用关心_listen_sockfd因为父进程在listen。子进程只服务就好// close(_listen_sockfd);// if(fork()0)// exit(0);// //孙子进程 父进程退出了他变成孤儿进程// //被操作系统领养 死亡自动回收不需要wait了// Service1(sockfd);// close(sockfd);// exit(0);// }// else// {// //父进程// close(sockfd); //sockfd交给子进程去服务了// //nullptr代表不需要子进程的退出信息0代表阻塞等待// pid_t rid waitpid(id,nullptr,0);// if(rid id)// {// //等待成功 //去干你想干的事情// }// }// v3 多进程 信号版本 //与104行signal(SIGCHLD,SIG_IGN);一起使用// 通过信号忽略的方式让父进程不再管子进程// pid_t id fork();// if(id 0)// {// close(sockfd);// continue;// }// else if(id 0)// {// //子进程// close(_listen_sockfd);// Service1(sockfd);// close(sockfd);// exit(0);// }// else// {// //父进程// close(sockfd);// }// v4 多线程版本// ThreadData *td new ThreadData(sockfd,peer);// //不直接传sockfd是担心主线程while循坏去将sockfd覆盖因此传递对象指针// func_t f bind(TcpServer::HandlerRequest,this,placeholders::_1);// thread t1(f,td);// t1.detach();// v5 线程池版本task_t f bind(TcpServer::Routine, this, sockfd, peer);kky::ThreadPooltask_t::GetInstance()-Push(f);}}//服务器去读取客户端的输入信息依据输入提供服务string Read(int sockfd){char buff[1024];ssize_t n read(sockfd, buff, sizeof(buff) - 1);if (n 0){buff[n] 0;}else if (n 0) // 表示对面关闭了连接{lg.LogMessage(Info, client quit...);}else{lg.LogMessage(Error, read socket error, \errno code: %d,error string: %s,errno, strerror(errno));}return buff;}void Routine(int sockfd,InetAddr addr){funcs[defaultService](sockfd,addr);string type Read(sockfd);lg.LogMessage(Debug,%s select %s,addr.PrintDebug().c_str(),type.c_str());if(type ping)funcs[type](sockfd,addr);else if(type translate)funcs[type](sockfd,addr);else funcs[defaultService](sockfd,addr);close(sockfd);}void DefaultService(int sockfd,InetAddr addr){std::string service_list | ;for(auto func : funcs){service_list func.first; service_list | ;}write(sockfd,service_list.c_str(),service_list.size());}// 添加string-callback_t 方法的映射void RegisterFunc(const string name, callback_t func){funcs[name] func;}~TcpServer(){}private:uint16_t _port;int _listen_sockfd;bool _isrunning;// 输入xxx 就去执行 xxx 任务unordered_mapstring, callback_t funcs; }; Main.cc   服务端的入口 #include TcpServer.hpp#include memoryusing namespace std;string unknown unknown; class Dictionary { public:Dictionary(){dict.insert(make_pairstring,string(banana,香蕉));dict.insert(make_pairstring,string(apple,苹果));dict.insert(make_pairstring,string(monkey,猴子));dict.insert(make_pairstring,string(love,爱));}string Excute(const string word){if(dict.find(word)!dict.end())return dict[word];return unknown;}~Dictionary(){} private:unordered_mapstring,string dict; };Dictionary ts;void Usage(string proc) {cout Usage \n\t proc local_port\n endl; }//判断服务器是否正常运行————心跳机制 客户ping就会获得pong 证明服务端没问题 void Ping(int sockfd, InetAddr addr) {lg.LogMessage(Debug, %s select %s success, fd : %d, addr.PrintDebug().c_str(), ping, sockfd);char buffer[1024];ssize_t n read(sockfd, buffer, sizeof(buffer) - 1);if (n 0)buffer[n] 0;string echo_string Pong;write(sockfd,echo_string.c_str(),echo_string.size()); }void Translate(int sockfd, InetAddr addr) {lg.LogMessage(Debug, %s select %s success, fd : %d, addr.PrintDebug().c_str(), translate, sockfd);char wordbuf[128];ssize_t n read(sockfd, wordbuf, sizeof(wordbuf) - 1);if (n 0)wordbuf[n] 0;string chinese ts.Excute(wordbuf);write(sockfd,chinese.c_str(),chinese.size());lg.LogMessage(Debug,%s Translate service,%s-%s,addr.PrintDebug().c_str(),wordbuf,chinese.c_str()); }int main(int argc, char *argv[]) {if (argc ! 2){Usage(argv[0]);return Usage_Err;}uint16_t port stoi(argv[1]);unique_ptrTcpServer tsvr(new TcpServer(port));tsvr-RegisterFunc(ping, Ping);tsvr-RegisterFunc(translate, Translate);tsvr-Init();tsvr-Start(); } TcpClient.cc   客户端的入口 #include iostream #include string #include cstring #include stdlib.h #include sys/types.h #include sys/socket.h #include netinet/in.h #include arpa/inet.h #include unistd.h #include signal.h #include Comm.hpp using namespace std;#define Retry_Count 5void Usage(string proc) {cout Usage \n\t proc local_ip local_port\n endl; }bool VisitServer(const string ip, const uint16_t port, int cnt) {int n 0;string inbuffer;char service_list[1024];ssize_t w 0; // write 返回值由于goto原因 需要放在前面ssize_t r 0; // read 返回值由于goto原因 需要放在前面bool ret true;// 1.创建套接字int sockfd socket(AF_INET, SOCK_STREAM, 0);if (sockfd 0){cerr socket error endl;ret false;goto END;}// 2.填写sockaddr_in信息struct sockaddr_in server;memset(server, 0, sizeof(server));server.sin_family AF_INET;server.sin_port htons(port);// inet_pton 类似于 inet_addr 都是让点分十进制 IP 转网络字节序的二进制序列inet_pton(AF_INET, ip.c_str(), server.sin_addr.s_addr);// 3.connect进行连接他会自动绑定不需要手动绑定n connect(sockfd, (struct sockaddr *)server, sizeof(server));if (n 0){cerr connect error endl;ret false;goto END;}//先读取操作列表r read(sockfd, service_list, sizeof(service_list) - 1);if (r 0){service_list[r] 0;cout 服务器提供的服务列表是 service_list endl;}cnt 1; // 让cnt又从1-5再次链接cout Please Select Service# ;getline(cin, inbuffer);// connect并没有产生新的sockfd只用这一个sockfd进行通信即可。w write(sockfd, inbuffer.c_str(), inbuffer.size());if (w 0){char buffer[1024];cout Please Enter# ;getline(cin, inbuffer);write(sockfd, inbuffer.c_str(), inbuffer.size());r read(sockfd, buffer, sizeof(buffer) - 1);if (r 0){buffer[r] 0;cout buffer endl;}else if (r 0) // read返回值为0代表读端关闭算是正常结束{goto END;}else{ret false;goto END;}}else if (w 0){cout 你并没有输入 endl;}else{cout write时服务器关闭 endl;ret false;} END:close(sockfd);return ret; }int main(int argc, char *argv[]) {if (argc ! 3){Usage(argv[0]);exit(Usage_Err);}signal(SIGPIPE, SIG_IGN);string ip argv[1];uint16_t port stoi(argv[2]);// 断线重连int cnt 1;while (cnt Retry_Count){int result VisitServer(ip, port, cnt);if (result)break;else{sleep(1);cout server offline, retrying..., count: cnt endl;}}if (cnt Retry_Count){cout server offline endl;} } Makefile 一键构建代码 .PHONY:all all:tcp_server tcp_client tcp_server:Main.ccg -o $ $^ -stdc11 -lpthread tcp_client:TcpClient.ccg -o $ $^ -stdc11 -lpthread .PHONY:clean clean:rm -f tcp_server tcp_client 代码链接 运行结果如下
http://www.dnsts.com.cn/news/147396.html

相关文章:

  • 自己建设个小网站要什么手续军博网站建设公司
  • 有没有学做蛋糕的网站和视频北京专业建设网站公司
  • 网络科技公司网站源码网站排名优化工具
  • 做家旅游的视频网站好wordpress读书插件
  • 网站建设免费模板wordpress目录遍历漏洞
  • joomla! 1.5 网站建设基础教程河间网站建设推广
  • 机械厂做网站到底有没有效果重庆建工第二建设有限公司网站
  • 西安房产网站制作公司安徽黄山网站建设
  • 重庆企业网站定制优就业seo课程学多久
  • 看那种片哪个网站好用google ajax wordpress
  • 北京国都建设集团网站商标注册代理
  • 泰安网站建设报价著名的个人网站
  • 做家居网站微信推广方案
  • 网站建设html5模板Wordpress 自用主题 免费 分享
  • 网站自主建站韩国美容网站模板
  • 长春网站建设v1手机装修设计软件
  • 百度网站ip地址漯河网站建设zrgu
  • 深圳横岗做网站网站建设合同副本
  • 没有影视许可怎么用国内空间做网站软件定制开发网站建设
  • 网站建设免费域名旅行社服务网点能否做网站
  • 湖北外贸网站建设费用企业解决方案是什么
  • 美食网站要怎么做wordpress主题开发教程
  • 公司核准名称网站千库网素材免费下载
  • 北京市网站公司wordpress 返回上一页
  • 铜仁市城乡住房与建设局网站j2ee网站开发实例
  • 网站怎样做注册窗口邯郸做网站费用
  • 现在公司做各网站要多少钱网站备案 和 icp
  • 奥运网站模板建筑公司二级资质要求
  • 如何建立英文网站推销广告
  • 网站访问速度跟服务器cpu和内存和带宽哪个重要h5自适应网站源码