基于Socket和UDP协议搭建简单服务器并实现英译汉的功能

服务端

封装UDPSocket

#pragma once
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <cassert>
#include <string>
#include <unistd.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>

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 <functional>
typedef std::function<void (std::string&, std::string* resp)> 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 <unordered_map>
#include <iostream>

std::unordered_map<std::string, std::string> 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 <assert.h>
#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 <iostream>

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协议实现简单英译汉功能

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值