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

医院内外网站建设seo工资

医院内外网站建设,seo工资,安泽网站建设,网站怎么做评论文章目录 2. 实现一个简易的聊天室应用2.1 log.hpp - 日志记录系统2.2 Terminal.hpp - 终端重定向管理器2.3 UdpClient.cc - 多线程聊天客户端2.4 UdpServer.hpp - 广播式聊天服务器2.5 main.cc - 服务器启动程序 2. 实现一个简易的聊天室应用 2.1 log.hpp - 日志记录系统 lo…

文章目录

  • 2. 实现一个简易的聊天室应用
    • 2.1 log.hpp - 日志记录系统
    • 2.2 Terminal.hpp - 终端重定向管理器
    • 2.3 UdpClient.cc - 多线程聊天客户端
    • 2.4 UdpServer.hpp - 广播式聊天服务器
    • 2.5 main.cc - 服务器启动程序


2. 实现一个简易的聊天室应用

2.1 log.hpp - 日志记录系统

log.hpp

#pragma once  // 防止头文件被重复包含// 包含必要的头文件
#include <iostream>     // 标准输入输出
#include <time.h>      // 时间相关函数
#include <stdarg.h>    // 可变参数函数支持
#include <sys/types.h> // 系统类型定义
#include <sys/stat.h>  // 文件状态
#include <fcntl.h>     // 文件控制
#include <unistd.h>    // UNIX标准函数
#include <stdlib.h>    // 标准库函数#define SIZE 1024  // 缓冲区大小// 定义日志级别
#define Info 0     // 普通信息
#define Debug 1    // 调试信息
#define Warning 2  // 警告信息
#define Error 3    // 错误信息
#define Fatal 4    // 致命错误// 定义日志输出方式
#define Screen 1     // 输出到屏幕
#define Onefile 2    // 输出到单个文件
#define Classfile 3  // 按日志级别分类输出#define LogFile "log.txt"  // 默认日志文件名class Log
{
public:// 构造函数:初始化日志系统Log(){printMethod = Screen;    // 默认输出到屏幕path = "./log/";         // 默认日志目录}// 设置日志输出方式void Enable(int method){printMethod = method;}// 将日志级别转换为对应的字符串std::string levelToString(int level){switch (level){case Info:    return "Info";case Debug:   return "Debug";case Warning: return "Warning";case Error:   return "Error";case Fatal:   return "Fatal";default:      return "None";}}// 根据输出方式打印日志void printLog(int level, const std::string &logtxt){switch (printMethod){case Screen:     // 输出到屏幕std::cout << logtxt << std::endl;break;case Onefile:    // 输出到单个文件printOneFile(LogFile, logtxt);break;case Classfile:  // 按级别输出到不同文件printClassFile(level, logtxt);break;default:break;}}// 将日志写入指定文件void printOneFile(const std::string &logname, const std::string &logtxt){std::string _logname = path + logname;// 打开文件:只写、如果不存在则创建、追加写入int fd = open(_logname.c_str(), O_WRONLY | O_CREAT | O_APPEND, 0666);if (fd < 0)return;write(fd, logtxt.c_str(), logtxt.size());  // 写入日志内容close(fd);  // 关闭文件}// 根据日志级别写入不同文件void printClassFile(int level, const std::string &logtxt){std::string filename = LogFile;filename += ".";filename += levelToString(level);  // 例如:log.txt.DebugprintOneFile(filename, logtxt);}// 重载函数调用运算符,实现格式化日志输出void operator()(int level, const char *format, ...){// 1. 获取时间信息time_t t = time(nullptr);struct tm *ctime = localtime(&t);// 2. 格式化时间和级别信息char leftbuffer[SIZE];snprintf(leftbuffer, sizeof(leftbuffer), "[%s][%d-%d-%d %d:%d:%d]", levelToString(level).c_str(),ctime->tm_year + 1900,    // 年(从1900年开始)ctime->tm_mon + 1,        // 月(0-11,需要+1)ctime->tm_mday,           // 日ctime->tm_hour,           // 时ctime->tm_min,            // 分ctime->tm_sec);           // 秒// 3. 处理可变参数va_list s;                         // 定义可变参数列表va_start(s, format);               // 初始化可变参数列表char rightbuffer[SIZE];            // 存储格式化后的可变参数vsnprintf(rightbuffer, sizeof(rightbuffer), format, s);va_end(s);                         // 清理可变参数列表// 4. 组合完整日志消息char logtxt[SIZE * 2];snprintf(logtxt, sizeof(logtxt), "%s %s", leftbuffer, rightbuffer);// 5. 输出日志printLog(level, logtxt);}private:int printMethod;        // 日志输出方式std::string path;       // 日志文件路径
};/* 可变参数示例
int sum(int n, ...)
{va_list s;           // 定义可变参数列表va_start(s, n);      // 初始化,n是最后一个固定参数int sum = 0;while(n){sum += va_arg(s, int);  // 依次获取int类型的参数n--;}va_end(s);          // 清理可变参数列表return sum;
}
*/

2.2 Terminal.hpp - 终端重定向管理器

Terminal.hpp

// 包含必要的头文件
#include <iostream>      // 标准输入输出流
#include <string>        // 字符串类
#include <unistd.h>     // UNIX标准函数,提供dup2等系统调用
#include <sys/types.h>  // 基本系统数据类型
#include <sys/stat.h>   // 文件状态信息
#include <fcntl.h>      // 文件控制选项// 指定终端设备路径
// /dev/pts/N 是伪终端(pseudo-terminal)的设备文件
// 数字N表示特定的终端编号
std::string terminal = "/dev/pts/6";// 打开并重定向到指定终端的函数
int OpenTerminal()
{// 以只写模式打开终端设备// O_WRONLY: 以只写方式打开int fd = open(terminal.c_str(), O_WRONLY);// 错误处理:如果打开失败if(fd < 0){std::cerr << "open terminal error" << std::endl;return 1;}// 重定向标准错误输出(stderr)到新打开的终端// dup2(oldfd, newfd):将newfd重定向到oldfd// 2代表标准错误输出(stderr)dup2(fd, 2);/* 测试代码(已注释)// printf("hello world\n");// close(fd);*/return 0;
}

这段代码的主要功能是:

  1. 打开一个指定的伪终端设备(/dev/pts/6)
  2. 将标准错误输出重定向到这个终端
  3. 这样所有的错误信息都会显示在指定的终端上

使用场景:

  • 调试输出重定向
  • 日志输出到特定终端
  • 多终端输出管理

注意事项:

  1. 需要确保目标终端(/dev/pts/6)存在且有写权限
  2. 终端编号(6)可能需要根据实际情况调整
  3. 使用完后应该关闭文件描述符(当前未实现)

2.3 UdpClient.cc - 多线程聊天客户端

UdpClient.cc

// 必要的头文件
#include <iostream>      // 标准输入输出
#include <cstdlib>      // 标准库函数
#include <unistd.h>     // UNIX标准函数
#include <strings.h>    // bzero等字符串操作
#include <string.h>     // 字符串操作
#include <sys/types.h>  // 基本系统数据类型
#include <sys/socket.h> // 套接字接口
#include <netinet/in.h> // Internet地址族
#include <arpa/inet.h>  // IP地址转换函数
#include <pthread.h>    // POSIX线程
#include "Terminal.hpp" // 终端操作using namespace std;// 打印使用说明
void Usage(std::string proc)
{std::cout << "\n\rUsage: " << proc << " serverip serverport\n"<< std::endl;
}// 线程间共享数据结构
struct ThreadData
{struct sockaddr_in server; // 服务器地址信息int sockfd;               // 套接字描述符std::string serverip;     // 服务器IP地址
};// 接收消息的线程函数
void *recv_message(void *args)
{// OpenTerminal(); // 可选的终端重定向ThreadData *td = static_cast<ThreadData *>(args); // 类型转换char buffer[1024]; // 接收缓冲区while (true){memset(buffer, 0, sizeof(buffer)); // 清空缓冲区struct sockaddr_in temp;           // 临时存储发送方地址socklen_t len = sizeof(temp);// 接收数据// sockfd: 套接字描述符// buffer: 接收缓冲区// 1023: 接收大小(留1字节给\0)// flags: 0// temp: 发送方地址// len: 地址结构长度ssize_t s = recvfrom(td->sockfd, buffer, 1023, 0, (struct sockaddr *)&temp, &len);if (s > 0){buffer[s] = 0;        // 添加字符串结束符cerr << buffer << endl; // 输出接收到的消息}}
}// 发送消息的线程函数
void *send_message(void *args)
{ThreadData *td = static_cast<ThreadData *>(args);string message;socklen_t len = sizeof(td->server);// 发送欢迎消息std::string welcome = td->serverip;welcome += " comming...";sendto(td->sockfd, message.c_str(), message.size(), 0, (struct sockaddr *)&(td->server), len);// 循环发送用户输入的消息while (true){cout << "Please Enter@ ";getline(cin, message); // 获取用户输入// 发送消息到服务器sendto(td->sockfd, message.c_str(), message.size(), 0, (struct sockaddr *)&(td->server), len);}
}// 主函数
// 使用方式:./udpclient serverip serverport
int main(int argc, char *argv[])
{// 检查命令行参数if (argc != 3){Usage(argv[0]);exit(0);}// 获取服务器IP和端口std::string serverip = argv[1];uint16_t serverport = std::stoi(argv[2]);// 初始化线程数据结构struct ThreadData td;bzero(&td.server, sizeof(td.server));           // 清零服务器地址结构td.server.sin_family = AF_INET;                 // 使用IPv4td.server.sin_port = htons(serverport);         // 设置端口(转换为网络字节序)td.server.sin_addr.s_addr = inet_addr(serverip.c_str()); // 设置IP地址// 创建UDP套接字td.sockfd = socket(AF_INET, SOCK_DGRAM, 0);if (td.sockfd < 0){cout << "socker error" << endl;return 1;}td.serverip = serverip;// 创建接收和发送线程pthread_t recvr, sender;pthread_create(&recvr, nullptr, recv_message, &td);  // 创建接收线程pthread_create(&sender, nullptr, send_message, &td); // 创建发送线程// 等待线程结束pthread_join(recvr, nullptr);pthread_join(sender, nullptr);// 清理资源close(td.sockfd);return 0;
}

工作流程:

初始化↓
创建套接字↓
创建线程 ─┬─→ 接收线程: 循环接收服务器消息└─→ 发送线程: 循环发送用户输入↓
等待线程结束↓
清理资源

代码功能总结:

  1. 创建UDP套接字与服务器通信
  2. 使用多线程分别处理消息的发送和接收
  3. 发送线程负责获取用户输入并发送
  4. 接收线程负责显示来自服务器的消息
  5. 实现了简单的聊天室客户端功能

主要特点:

  1. 使用UDP协议进行通信
  2. 多线程设计,支持同时收发消息
  3. 支持命令行参数配置服务器地址

2.4 UdpServer.hpp - 广播式聊天服务器

UdpServer.hpp

#pragma once  // 防止头文件重复包含// 必要的头文件包含
#include <iostream>      // 标准输入输出
#include <string>        // 字符串类
#include <strings.h>     // bzero等字符串操作
#include <cstring>       // C风格字符串操作
#include <sys/types.h>   // 基本系统数据类型
#include <sys/socket.h>  // 套接字接口
#include <netinet/in.h>  // Internet地址族
#include <arpa/inet.h>   // IP地址转换函数
#include <functional>    // std::function
#include <unordered_map> // 哈希表
#include "Log.hpp"       // 日志系统// 定义回调函数类型:处理消息并返回响应
// 参数:消息内容、客户端IP、客户端端口
typedef std::function<std::string(const std::string &, const std::string &, uint16_t)> func_t;// 全局日志对象
Log lg;// 错误码枚举
enum {SOCKET_ERR = 1,  // 套接字创建错误BIND_ERR         // 绑定错误
};// 默认配置
uint16_t defaultport = 8080;              // 默认端口号
std::string defaultip = "0.0.0.0";        // 默认IP(监听所有网卡)
const int size = 1024;                    // 缓冲区大小// UDP服务器类
class UdpServer {
public:// 构造函数:初始化服务器参数UdpServer(const uint16_t &port = defaultport, const std::string &ip = defaultip):sockfd_(0), port_(port), ip_(ip), isrunning_(false){}// 初始化服务器void Init(){// 创建UDP套接字// AF_INET: IPv4协议族// SOCK_DGRAM: UDP数据报套接字sockfd_ = socket(AF_INET, SOCK_DGRAM, 0);if(sockfd_ < 0){lg(Fatal, "socket create error, sockfd: %d", sockfd_);exit(SOCKET_ERR);}lg(Info, "socket create success, sockfd: %d", sockfd_);// 绑定套接字到指定地址和端口struct sockaddr_in local;bzero(&local, sizeof(local));           // 清零地址结构local.sin_family = AF_INET;             // 使用IPv4local.sin_port = htons(port_);          // 端口转换为网络字节序local.sin_addr.s_addr = inet_addr(ip_.c_str()); // IP转换为网络字节序// local.sin_addr.s_addr = htonl(INADDR_ANY);   // 替代方案:监听所有网卡// 绑定套接字if(bind(sockfd_, (const struct sockaddr *)&local, sizeof(local)) < 0){lg(Fatal, "bind error, errno: %d, err string: %s", errno, strerror(errno));exit(BIND_ERR);}lg(Info, "bind success, errno: %d, err string: %s", errno, strerror(errno));}// 检查并添加新用户void CheckUser(const struct sockaddr_in &client, const std::string clientip, uint16_t clientport){auto iter = online_user_.find(clientip);if(iter == online_user_.end())  // 如果是新用户{online_user_.insert({clientip, client});  // 添加到在线用户列表std::cout << "[" << clientip << ":" << clientport << "] add to online user." << std::endl;}}// 广播消息给所有在线用户void Broadcast(const std::string &info, const std::string clientip, uint16_t clientport){// 遍历所有在线用户for(const auto &user : online_user_){// 构造广播消息格式:[IP:PORT]# messagestd::string message = "[";message += clientip;message += ":";message += std::to_string(clientport);message += "]# ";message += info;// 发送消息给每个用户socklen_t len = sizeof(user.second);sendto(sockfd_, message.c_str(), message.size(), 0, (struct sockaddr*)(&user.second), len);}}// 运行服务器主循环void Run(){isrunning_ = true;char inbuffer[size];  // 接收缓冲区while(isrunning_){struct sockaddr_in client;     // 客户端地址结构socklen_t len = sizeof(client);// 接收数据ssize_t n = recvfrom(sockfd_, inbuffer, sizeof(inbuffer) - 1, 0, (struct sockaddr*)&client, &len);if(n < 0){lg(Warning, "recvfrom error, errno: %d, err string: %s", errno, strerror(errno));continue;}// 获取客户端信息uint16_t clientport = ntohs(client.sin_port);    // 转换为主机字节序std::string clientip = inet_ntoa(client.sin_addr); // 转换为点分十进制// 检查用户并广播消息CheckUser(client, clientip, clientport);std::string info = inbuffer;Broadcast(info, clientip, clientport);}}// 析构函数:清理资源~UdpServer(){if(sockfd_ > 0) close(sockfd_);}private:int sockfd_;      // 套接字文件描述符std::string ip_;  // 服务器IP地址uint16_t port_;   // 服务器端口号bool isrunning_;  // 服务器运行状态std::unordered_map<std::string, struct sockaddr_in> online_user_; // 在线用户表
};

服务器工作流程:

  1. 初始化:创建套接字并绑定到指定地址和端口
  2. 主循环:
    • 接收客户端消息
    • 检查是否是新用户
    • 广播消息给所有在线用户
  3. 关闭:清理资源

特点:

  1. 支持多客户端
  2. 消息广播功能
  3. 在线用户管理
  4. 集成日志系统

2.5 main.cc - 服务器启动程序

main.cc

#include "UdpServer.hpp"  // UDP服务器类
#include <memory>        // 智能指针
#include <cstdio>       // 标准输入输出
#include <vector>       // vector容器// "120.78.126.148" 点分十进制字符串风格的IP地址// 打印使用说明
void Usage(std::string proc)
{std::cout << "\n\rUsage: " << proc << " port[1024+]\n" << std::endl;
}// 主函数
// 使用方式:./udpserver port
int main(int argc, char *argv[])
{// 检查命令行参数if(argc != 2){Usage(argv[0]);exit(0);}// 获取端口号uint16_t port = std::stoi(argv[1]);// 创建UDP服务器实例(使用智能指针管理)std::unique_ptr<UdpServer> svr(new UdpServer(port));// 初始化服务器svr->Init();// 运行服务器svr->Run();return 0;
}

代码说明:

  1. 这是一个UDP服务器的主程序
  2. 支持命令行参数指定端口号
  3. 使用智能指针管理服务器实例
  4. 原本包含远程命令执行功能,但已被注释掉以提高安全性

被注释掉的功能:

  1. Handler: 消息处理函数
  2. SafeCheck: 命令安全检查
  3. ExcuteCommand: 命令执行功能

安全考虑:

  1. 移除了远程命令执行功能
  2. 去掉了可能造成系统危险的操作
  3. 将服务器功能限制为纯消息转发

使用方式:

./udpserver 8080 // 在8080端口启动服务器


文章转载自:

http://39U7pZSk.mddpj.cn
http://UvjJfMr5.mddpj.cn
http://G2U5LSDa.mddpj.cn
http://z9YDi83r.mddpj.cn
http://dRrIYXHC.mddpj.cn
http://yyXRPXDH.mddpj.cn
http://ULo2aRjb.mddpj.cn
http://o8myrCAF.mddpj.cn
http://VGhj62Bg.mddpj.cn
http://r7H499QS.mddpj.cn
http://NOEweVvv.mddpj.cn
http://VMEvNNGV.mddpj.cn
http://N1qxjbcV.mddpj.cn
http://fDe6t6T9.mddpj.cn
http://rIivaOA3.mddpj.cn
http://jU1KqbqQ.mddpj.cn
http://zLLR53nQ.mddpj.cn
http://ylqmfWGP.mddpj.cn
http://UvBEBnZq.mddpj.cn
http://7uB3fvSd.mddpj.cn
http://Lnrlbo4L.mddpj.cn
http://YJwyJfDi.mddpj.cn
http://3O3m8SnS.mddpj.cn
http://6DPfG3tp.mddpj.cn
http://9IB9HXxG.mddpj.cn
http://T4Iugfq9.mddpj.cn
http://cQfrWP6i.mddpj.cn
http://aEjvqm4d.mddpj.cn
http://26zhDAsE.mddpj.cn
http://W9YFK0U0.mddpj.cn
http://www.dtcms.com/wzjs/643594.html

相关文章:

  • 宁乡县建设局网站产品推广的重要性
  • 网站运营经验分享ppt企业网站在哪里建
  • 网站设计公司建设做网站建设怎么介绍自己
  • 苏州网站建设推荐好先生科技西安装修公司排名十强
  • 郑州企业招聘衡水网站排名优化公司
  • 网站建设西街wordpress用户勾选
  • 视频模板在线制作网站有网站源码如何建站
  • 源码开发网站建设北京网站如何做推广
  • 织梦网站首页空白做自适应网站
  • 南京市建设工程档案馆网站h5特效网站欣赏
  • 个人优秀网站欣赏html5做网站的代码
  • wordpress改网站信息seo全网优化推广
  • 长沙 网站开发黑龙江省建设协会网站
  • 注册一个做网站的公司php做公司网站
  • 青冈网站建设在百度上做网站有用吗
  • 广告案例的网站自媒体平台注册入口账
  • 做网站后台需要写代码吗网站很卡如何优化
  • 东莞贸易公司寮步网站建设价格wordpress 淘客网站
  • 中山市做网站实力一般网站的后台
  • 做模具五金都是用的那个网站网站开发用linux
  • 网站最好推广的方式免费在线做网站
  • 百度小程序制作网站网站设计公司哪家好
  • 本科生做网站编辑海尔网站建设情况
  • 网站模板图片木马网站怎么做
  • 网站建设会用什么软件有哪些网站 建设标准
  • 申请网站域名多少钱知识库管理系统解决方案
  • 网站销售流程软装设计网络课程
  • 程序天下:lamp网站开发黄金组合 pdf阿里云国际站官网
  • 配送网站开发合肥网络公司 网站建设
  • 实惠的网站建设公司头像制作免费