封装UDPSocket
#pragma once
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
typedef struct sockaddr sockaddr;
typedef struct sockaddr_in sockaddr_in;
class UdpSocket {
public:
UdpSocket() :
fd_(-1) { }
bool Socket() {
fd_ = socket(AF_INET, SOCK_DGRAM, 0);//创建socket
if (fd_ < 0) {
perror("socket");
return false;
}
return true;
}
bool Close() {
close(fd_);
return true;
}
//绑定端口
bool Bind(const std::string &ip, uint16_t port) {
sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = inet_addr(ip.c_str());
addr.sin_port = htons(port);
int ret = bind(fd_, (sockaddr*)&addr, sizeof(addr));
if (ret < 0) {
perror("bind");
return false;
}
return true;
}
bool RecvFrom(std::string* buf, std::string *ip = NULL, uint16_t *port = NULL) {
char tmp[1024 * 10] = { 0 };
sockaddr_in peer;
socklen_t len = sizeof(peer);
ssize_t read_size = recvfrom(fd_, tmp, sizeof(tmp) - 1, 0, (sockaddr*)&peer, &len);
if (read_size < 0) {
perror("recvform");
return false;
}
//将读到的缓冲区内容放到输出参数中
buf->assign(tmp, read_size);
if (ip != NULL) {
*ip = inet_ntoa(peer.sin_addr);
}
if (port != NULL) {
*port = ntohs(peer.sin_port);
return true;
}
}
bool SendTo(const std::string &buf, const std::string &ip, uint16_t port) {
sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = inet_addr(ip.c_str());
addr.sin_port = htons(port);
ssize_t write_size = sendto(fd_, buf.data(), buf.size(), 0, (sockaddr*)&addr, sizeof(addr));
if (write_size < 0) {
perror("sendto");
return false;
}
return true;
}
private:
int fd_;
};
搭建UDP通用服务器
#pragma once
#include "udp_socket.hpp"
//C 式写法
//typedef void (Handler*)(const std::string &req, std::dtring* resp);
#include
typedef std::function Handler;
class UdpServer {
public:
UdpServer() {
assert(sock_.Socket());
}
~UdpServer() {
sock_.Close();
}
bool Start(const std::string& ip, uint16_t port, Handler handler) {
//1、创建socket
//2、绑定端口
bool ret = sock_.Bind(ip, port);
if (!ret) {
return false;
}
//3、进入时间循环
while (1) {
//4、尝试读取请求
std::string req;
std::string remote_ip;
uint16_t remote_port = 0;
bool ret = sock_.RecvFrom(&req, &remote_ip, &remote_port);
if (!ret) {
continue;
}
std::string resp;
//5、根据请求计算响应
handler(req, &resp);
//6、返回相应给客户端
sock_.SendTo(resp, remote_ip, remote_port);
printf("[%s:%d] req: %s, resp: %s\n", remote_ip.c_str(), remote_port, req.c_str(), resp.c_str());
}
sock_.Close();
return true;
}
private:
UdpSocket sock_;
};
实现英译汉服务器
//这是基于对udp服务器通用接口的封装,实现一个查字典的服务器
#include "udp_server.hpp"
#include
#include
std::unordered_map g_dict;
void Translate(const std::string& req, std::string *resp) {
auto it = g_dict.find(req);
if(it == g_dict.end()) {
*resp = "未查到!";
return ;
}
*resp = it->second;
}
int main(int argc, char* argv[]){
//printf("%d", argc);
if(argc != 3) {
printf ("Usage ./dict_server [ip] [port]\n");
return 1;
}
//1、数据初始化
g_dict.insert(std::make_pair("hello", "你好"));
g_dict.insert(std::make_pair("world", "世界"));
g_dict.insert(std::make_pair("JacksonYee", "易烊千玺"));
g_dict.insert(std::make_pair("cool", "酷"));
//2、启动服务器
UdpServer server;
server.Start(argv[1], atoi(argv[2]), Translate);
return 0;
}
实现UDP通用客户端
#pragma once
#include
#include "udp_socket.hpp"
class UdpClient {
public:
UdpClient(const std::string& ip, uint16_t port) :
ip_(ip),
port_(port) {
assert(sock_.Socket());
}
~UdpClient() {
sock_.Close();
}
bool RecvFrom(std::string* buf) {
return sock_.RecvFrom(buf);
}
bool SendTo(const std::string& buf) {
return sock_.SendTo(buf, ip_, port_);
}
private:
UdpSocket sock_;
//服务器的IP和端口号
std::string ip_;
uint16_t port_;
};
实现英译汉客户端
#include "udp_client.hpp"
//#include
int main(int argc, char* argv[]) {
printf("%d\n", argc);
if (argc != 3) {
printf("Usage ./dict_client [ip] [port]\n");
return 1;
}
UdpClient client(argv[1], atoi(argv[2]));
while (1) {
std::string word;
std::cout << "Please enter the word:";
std::cin >> word;
if (!std::cin) {
std::cout << "Bye~" << std::endl;
break;
}
client.SendTo(word);
std::string result;
client.RecvFrom(&result);
std::cout << word << "means: " << result << std::endl;
}
return 0;
}
基于Socket和TCP协议实现简单英译汉功能