wordpress建站教程道一,在中国如何申请域名,安徽网站建设认准-晨飞网络,前端开发和网站建设V1 版本 - echo server 简单的回显服务器和客户端代码#xff0c;本地回环#xff0c;要求c#xff0c;s砸啊哎同一台机器#xff0c;本地通信#xff0c;client发送的数据不会被推送到网络#xff0c;而是在OS内部绕一圈交给对应的服务器#xff0c;一般用于网络代码的…V1 版本 - echo server 简单的回显服务器和客户端代码本地回环要求cs砸啊哎同一台机器本地通信client发送的数据不会被推送到网络而是在OS内部绕一圈交给对应的服务器一般用于网络代码的测试 Udpclient.cc
#include iostream
#includesys/socket.h
#includestring
#includestring.h
// 网络四剑客
#include sys/types.h
#include sys/socket.h
#include netinet/in.h
#include arpa/inet.h// ./udpclient server_ip server
int main(int argc, char *argv[])
{if (argc ! 3){std::cerr Usage: argv[0] ip port std::endl;return 1;}std::string server_ip argv[1];uint16_t server_port std::stoi(argv[2]);//1.创建套接字int sockfdsocket(AF_INET,SOCK_DGRAM,0);if(socket0){std::cerr创建套接字失败std::endl;return 2;}//2.绑定操作系统在首次发消息自动绑定无需用户bindOS知道IP端口号采用随机端口号为了避免用户端口冲突//2.5填写服务端信息struct sockaddr_in server;memset(server,0,sizeof(server));server.sin_familyAF_INET;server.sin_porthtons(server_port);server.sin_addr.s_addrinet_addr(server_ip.c_str());//3.发消息while(true){std::string input;std::cout请输入#;std::getline(std::cin,input);int n sendto(sockfd,input.c_str(),input.size(),0,(struct sockaddr*)server,sizeof(server));(void)n;char buffer[1024];struct sockaddr_in peer;socklen_t lensizeof(peer);int m recvfrom(sockfd,buffer,sizeof(buffer)-1,0,(struct sockaddr*)peer,len);if(m0){buffer[m]0;std::coutbufferstd::endl;}}return 0;
} Udpserver.cc
#include iostream
#include UdpServer.hpp
#include memory
using namespace std;// ./udpserver ip port
int main(int argc, char *argv[])
{if (argc ! 3){std::cerr Usage: argv[0] ip port std::endl;return 1;}std::string ip argv[1];uint16_t port std::stoi(argv[2]);Enable_Console_Log_Strategy();std::unique_ptrUdpServer usvr std::make_uniqueUdpServer(ip, port);usvr-Init();usvr-Start();return 0;
}
Udpserver.hpp
#pragma once
#include iostream
#include Log.hpp
#include Mutex.hpp
#include string
#include string.h
// 网络四剑客
#include sys/types.h
#include sys/socket.h
#include netinet/in.h
#include arpa/inet.husing namespace LogModule;
class UdpServer
{
public:UdpServer(const std::string ip, uint16_t port, int sockfd -1): _sockfd(sockfd), _ip(ip), _port(port) {}// 初始化void Init(){// 1.创建套接字 IPV4网络 面向数据包 UDP_sockfd socket(AF_INET, SOCK_DGRAM, 0);if (_sockfd 0){LOG(Loglevel::FATAL) 创建套接字失败_sockfd _sockfd;exit(1);}LOG(Loglevel::INIF) 创建套接字成功;// 2.绑定socket信息ip和端口ip// 2.1填充sockaddr_in结构体struct sockaddr_in local;local.sin_family AF_INET; // 网络通信local.sin_port htons(_port); // 转化网络序列local.sin_addr.s_addr inet_addr(_ip.c_str()); // 设置结构体内的addr ip转成4字节的网络序列//服务端IP和端口不能轻易改变所以需要显示绑定int n bind(_sockfd, (struct sockaddr *)local, sizeof(local)); // 将本地的套接字设置回内核if (n 0){LOG(Loglevel::FATAL) 绑定失败;exit(2);}LOG(Loglevel::INIF) 绑定成功,_sockfd: _sockfd;}// 启动服务器void Start(){_isrunning true;while(_isrunning){char buffer[1024];//缓冲区struct sockaddr_in peer; //基类socklen_t lensizeof(peer);//recvfrom 返回实际独到的大小读取失败返回-1//1.不断收消息 创建的sockfd 缓冲区 缓冲区大小 阻塞式IO对方不发消息一直阻塞如同scanf 传进的sockaddr结构体大小返回实际独到的结构体大小 ssize_t s recvfrom(_sockfd,buffer,sizeof(buffer)-1,0,(struct sockaddr*)peer,len);if(s0){buffer[s]0;LOG(Loglevel::DEBUG)buffer:buffer;//2.发消息std::string echp_stringserver say;echp_stringbuffer; // 发给谁 sendto(_sockfd,echp_string.c_str(),echp_string.size(),0,(struct sockaddr*)peer,len);}}}~UdpServer() {}private:int _sockfd; // 套接字描述符uint16_t _port; // 端口号std::string _ip; // ipbool _isrunning;
}; 其他辅助文件
锁
Mutex.hpp
#pragma once
#include pthread.h
#include iostream
namespace MutexModule
{ class Mutex{public:Mutex(){pthread_mutex_init(_mutex, nullptr);}void Lock(){int n pthread_mutex_lock(_mutex);(void)n;}void Unlock(){int n pthread_mutex_unlock(_mutex);(void)n;}~Mutex(){pthread_mutex_destroy(_mutex);}pthread_mutex_t *get(){return _mutex;}private:pthread_mutex_t _mutex;};class LockGuard{public:LockGuard(Mutex mutex):_mutex(mutex){_mutex.Lock();}~LockGuard(){_mutex.Unlock();}private:Mutex _mutex;};
}
日志
Log.hpp
#ifndef __LOG_HPP__
#define __LOG_HPP__#include iostream
#include string
#include Mutex.hpp
#include filesystem
#include fstream
#include memory
#include unistd.h
#include sstream
#includectimenamespace LogModule
{const std::string sep \r\n;using namespace MutexModule ;// 2.刷新策略class LogStrategy{public:~LogStrategy() default;virtual void SyncLog(const std::string message) 0;};// 显示器刷新日志的策略class ConsoleLogStrategy : public LogStrategy{public:ConsoleLogStrategy() {}~ConsoleLogStrategy() {}void SyncLog(const std::string message) override{LockGuard lockguard(_mutex);std::cout message sep;}private:Mutex _mutex;};// 缺省文件路径以及文件本身const std::string defaultpath ./log;const std::string defaultfile my.log;// 文件刷新日志的策略class FileLogStrategy : public LogStrategy{public:FileLogStrategy(const std::string path defaultpath, const std::string file defaultfile): _path(path), _file(file){LockGuard lockguard(_mutex);if (std::filesystem::exists(_path)) // 判断路径是否存在{return;}try{std::filesystem::create_directories(_path);}catch (const std::filesystem::filesystem_error e){std::cerr e.what() \n;}}void SyncLog(const std::string message) override{LockGuard lockguard(_mutex);std::string filename _path (_path.back() / ? : /) _file;std::ofstream out(filename, std::ios::app); // 追加写入if (!out.is_open()){return;}out message sep;out.close();}~FileLogStrategy() {}private:Mutex _mutex;std::string _path; // 日志文件的路径std::string _file; // 要打印的日志文件};// 形成日志等级enum class Loglevel{DEBUG,INIF,WARNING,ERROR,FATAL};std::string Level2Str(Loglevel level){switch (level){case Loglevel::DEBUG:return DEBUG;case Loglevel::INIF:return INIF;case Loglevel::WARNING:return WARNING;case Loglevel::ERROR:return ERROR;case Loglevel::FATAL:return FATAL;default:return UNKNOWN;}}std::string GetTimeStamp(){time_t cuur time(nullptr);struct tm curr_tm;localtime_r(cuur,curr_tm);char buffer[128];snprintf(buffer,sizeof(buffer),%4d-%02d-%02d %02d:%02d:%02d,curr_tm.tm_year1900,curr_tm.tm_mon1,curr_tm.tm_mday,curr_tm.tm_hour,curr_tm.tm_min,curr_tm.tm_sec);return buffer;}class Logger{public:Logger(){EnableConsoleLogStrategy();}// 选择某种策略// 1.文件void EnableFileLogStrategy(){_ffush_strategy std::make_uniqueFileLogStrategy();}// 显示器void EnableConsoleLogStrategy(){_ffush_strategy std::make_uniqueConsoleLogStrategy();}// 表示的是未来的一条日志class LogMessage{public:LogMessage(Loglevel level, std::string src_name, int line_number, Logger logger): _curr_time(GetTimeStamp()), _level(level), _pid(getpid()), _src_name(src_name), _line_number(line_number), _logger(logger){// 合并左半部分std::stringstream ss;ss [ _curr_time ] [ Level2Str(_level) ] [ _pid ] [ _src_name ] [ _line_number ] - ;_loginfo ss.str();}template typename TLogMessage operator(const T info){// 右半部分可变std::stringstream ss;ss info;_loginfo ss.str();return *this;}~LogMessage(){if (_logger._ffush_strategy){_logger._ffush_strategy-SyncLog(_loginfo);}}private:std::string _curr_time; // 日志时间Loglevel _level; // 日志状态pid_t _pid; // 进程pidstd::string _src_name; // 文件名称int _line_number; // 对应的行号std::string _loginfo; // 合并之后的一条完整信息Logger _logger;};LogMessage operator()(Loglevel level, std::string src_name, int line_number){return LogMessage(level, src_name, line_number, *this);}~Logger() {}private:std::unique_ptrLogStrategy _ffush_strategy;};//全局日志对象Logger logger;//使用宏简化用户操作获取文件名和行号// __FILE__ 一个宏替换完成后目标文件的文件名// __LINE__ 一个宏替换完成后目标文件对应的行号#define LOG(level) logger(level,__FILE__,__LINE__) #define Enable_Console_Log_Strategy() logger.EnableConsoleLogStrategy()#define Enable_File_Log_Strategy() logger.EnableFileLogStrategy()}#endif 内网IP和本地环回都可以 内网IP和本地地址不能互通此处不做演示
1.bind公网IP --不行 公网IP没有配置在机器里公网IP无法直接bind云服务器是内部处理过的
2.bind 127.0.0.1 ||bind 内网IP --可以
3.server bind 内网 127.0.0.1访问 --不行
4.server 127.0.0.1 client 内网访问 --不行
如果我们显示的进行绑定client未来访问的时候就必须使用server端bind的地址否则找不到
例如我绑定了127.0.0.1 8080 但是我用内网xxx 8080去访问找不到没有这个程序 服务器手动分配为零允许接受任何报文自动分配任意IP地址,否则指定IP只能对应的IP地址才能访问
Udpserver.hpp
#pragma once
#include iostream
#include Log.hpp
#include Mutex.hpp
#include string
#include string.h
// 网络四剑客
#include sys/types.h
#include sys/socket.h
#include netinet/in.h
#include arpa/inet.husing namespace LogModule;
class UdpServer
{
public:UdpServer(const std::string ip, uint16_t port, int sockfd -1): _sockfd(sockfd), _ip(ip), _port(port) {}// 初始化void Init(){// 1.创建套接字 IPV4网络 面向数据包 UDP_sockfd socket(AF_INET, SOCK_DGRAM, 0);if (_sockfd 0){LOG(Loglevel::FATAL) 创建套接字失败_sockfd _sockfd;exit(1);}LOG(Loglevel::INIF) 创建套接字成功;// 2.绑定socket信息ip和端口ip// 2.1填充sockaddr_in结构体struct sockaddr_in local;local.sin_family AF_INET; // 网络通信local.sin_port htons(_port); // 转化网络序列//手动分配local.sin_addr.s_addr inet_addr(_ip.c_str()); // 设置结构体内的addr ip转成4字节的网络序列//自动分配local.sin_addr.s_addrINADDR_ANY;//服务端IP和端口不能轻易改变所以需要显示绑定int n bind(_sockfd, (struct sockaddr *)local, sizeof(local)); // 将本地的套接字设置回内核if (n 0){LOG(Loglevel::FATAL) 绑定失败;exit(2);}LOG(Loglevel::INIF) 绑定成功,_sockfd: _sockfd;}// 启动服务器void Start(){_isrunning true;while(_isrunning){char buffer[1024];//缓冲区struct sockaddr_in peer; //基类socklen_t lensizeof(peer);//recvfrom 返回实际独到的大小读取失败返回-1//1.不断收消息 创建的sockfd 缓冲区 缓冲区大小 阻塞式IO对方不发消息一直阻塞如同scanf 传进的sockaddr结构体大小返回实际独到的结构体大小 ssize_t s recvfrom(_sockfd,buffer,sizeof(buffer)-1,0,(struct sockaddr*)peer,len);if(s0){buffer[s]0;LOG(Loglevel::DEBUG)buffer:buffer;//2.发消息std::string echp_stringserver say;echp_stringbuffer; // 发给谁 sendto(_sockfd,echp_string.c_str(),echp_string.size(),0,(struct sockaddr*)peer,len);}}}~UdpServer() {}private:int _sockfd; // 套接字描述符uint16_t _port; // 端口号std::string _ip; // ipbool _isrunning;
}; netstat -naup
内网公网本地都可以随意访问甚至另一台主机也能访问