用tcp实现英译汉字典

1.TCP
  • 传输层协议
  • 有连接
  • 可靠传输
  • 面向字节流
2.TCP socket API
// 创建 socket 文件描述符 (TCP/UDP, 客户端 + 服务器)
int socket(int domain, int type, int protocol);
// 绑定端口号 (TCP/UDP, 服务器)      
int bind(int socket, const struct sockaddr *address,socklen_t address_len);
// 开始监听socket (TCP, 服务器)这个函数本身不会堵塞,只是告诉内核一些信息
int listen(int socket, int backlog);
// 接收请求 (TCP, 服务器)阻塞
int accept(int socket, struct sockaddr* address,socklen_t* address_len);
// 建立连接 (TCP, 客户端)阻塞
int connect(int sockfd, const struct sockaddr *addr,socklen_t addrlen);
3.TCP的三次握手

tcp的三次握手是为了可靠性传输(和双方是否都支持TCP协议)

  • 客户端和服务器都有两个问题:1).我发的数据对面能不能接收,2).对面发的数据我能不能接收
  • 1.客户端先发一句,服务器接收;服务器知道 2)
  • 2.服务器回复一句,客户端接收;客户端知道 1)2)
  • 3.客户端回复一句,服务器接收;服务器知道 1)
4.TCP实现英译汉字典

在这里插入图片描述

封装socket

tcp_socket.hpp

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

using namespace std;

class TcpSocket{
 public:
    TcpSocket():_fd(-1){}
    TcpSocket(int fd):_fd(fd){}

    bool Socket(){
        _fd = socket(AF_INET,SOCK_STREAM,0);
        if(_fd < 0){
            cerr<<"socket";
            return false;
        }
        clog<<"open fd = "<<_fd<<endl;
        return true;
    }
    bool Close()const{
        close(_fd);
        clog<<"close fd = "<<_fd<<endl;
        return true;
    }

    bool Bind(const string& ip, uint16_t port)const
    {
        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){
            cerr<<"bind false";
            return false;
        } 
        clog<<"bind success"<<endl;
        return true;
    }

    bool Listen(int num) const
    {
        int ret = listen(_fd, num);
        if(ret < 0)
        {
            cerr<<"listen false";
            return false;
        }
        clog<<"listen true"<<endl;
        return true;
    }
    bool Accept(TcpSocket* peer, string* ip = NULL, uint16_t* port = NULL)const
    {
        sockaddr_in peer_addr;
        socklen_t len = sizeof(peer_addr);
        int new_sock = accept(_fd,(sockaddr*)&peer_addr,&len);
        if(new_sock < 0){
            cerr<<"accept false";
            return false;
        }
        clog<<"accept fd= "<<new_sock<<endl;
        peer->_fd = new_sock;
        if(ip!=NULL)
        {
            *ip = inet_ntoa(peer_addr.sin_addr);
        }
        if(port!=NULL)
        {
            *port = ntohs(peer_addr.sin_port);
        }
        return true;
    }

    bool Recv(string* buf) const
    {
        buf->clear();
        char tmp[1024*10] = {0};
        ssize_t read_size = recv(_fd, tmp, sizeof(tmp),0);
        if(read_size < 0){
            cerr<<"recv false";
            return false;
        }
        if(read_size == 0)
        return false;

        buf->assign(tmp,read_size);
        return true;
    }

    bool Send(string& buf)const
    {
        ssize_t write_size = send(_fd,buf.data(),buf.size(),0);
        if(write_size < 0)
        {
            cerr<<"send false";
            return false;
        }
        return true;
    }

    bool Connect(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 = connect(_fd,(sockaddr*)&addr, sizeof(addr));
         
        if(ret < 0){
            cerr<<"connect false";
            return false;
        }
        return true;
    }

    int GetFd()const
    {
        return _fd;
    }
 private:
    int _fd;
};
封装一个通用TCP服务器

tcp_server.hpp

#pragma once
#include<functional>
#include"tcp_socket.hpp"
typedef std::function<void (string& req, string* resp)> Handler;
class TcpServer
{
 public:
    TcpServer(const string& ip, uint16_t port):_ip(ip),_port(port){}

    bool Start(Handler handler)
    {
        //1.创建socket
        _listen_sock.Socket();
        //2.绑定端口号
        _listen_sock.Bind(_ip,_port);
        //3.进行监听
        _listen_sock.Listen(5);
        //4.进入事件循环
        while(1)
        {
          //5.进行accept
          TcpSocket new_sock;
          string peer_addr;
          uint16_t peer_port;
          if(!_listen_sock.Accept(&new_sock,&peer_addr,&peer_port)){
            continue;
          }
          clog<<"[client "<<peer_addr<<": "<<peer_port<<"]";
          clog<<"客户端已连接"<<endl;
          //6.进行循环读写
          while(1)
          {
            string req;
            //7. 读取请求,读取失败则结束循环
            bool ret = new_sock.Recv(&req);
            if(!ret){
              clog<<"[client "<<peer_addr<<": "<<peer_port<<"]";
              clog<<"客户端关闭"<<endl;
              new_sock.Close();
              break;
            }
            //8.根据请求计算响应
            string resp;
            handler(req,&resp);
            //9.写回响应
            new_sock.Send(resp);
            clog<<"[client "<<peer_addr<<": "<<peer_port<<"]";
            clog<<"req "<<req<<endl;
            clog<<"resp "<<resp<<endl;
          }
        }
        return true;
    }
 private:
    TcpSocket _listen_sock;
    string _ip;
    uint16_t _port;
};
封装一个通用TCP客户端

tcp_client.hpp

#pragma once
#include"tcp_socket.hpp"

class TcpClient
{
  public:
  TcpClient(const string& ip, uint16_t port):_ip(ip),_port(port)
  {
    _sock.Socket();
  }
  ~TcpClient()
  {
    _sock.Close();
  }

  bool Connect(){
    return _sock.Connect(_ip,_port);
  }

  bool Recv(string* buf)
  {
    return _sock.Recv(buf);
  }

  bool Send(string& buf)
  {
    return _sock.Send(buf);
  }
  private:
    TcpSocket _sock;
    string _ip;
    uint16_t _port;
};
服务器代码:

server.cc

#include<iostream>
#include"tcp_server.hpp"
#include<unordered_map>

using namespace std;

unordered_map<string,string> dict;
void handler(const string& req, string* resq)
{
  auto it = dict.find(req);
  if(it == dict.end())
  {
    *resq = "未找到";
    clog<<*resq<<endl;
    return;
  }
  *resq = it->second;
    clog<<*resq<<endl;
}
int main(int argc, char* argv[])
{
  if(argc != 3){
    printf("请输入 [ip] [port]\n");
    return 0;
  }
  dict.insert(make_pair("hehe","呵呵"));
  dict.insert(make_pair("hi","嗨"));
  dict.insert(make_pair("hello","你好"));
  TcpServer s(argv[1],atoi(argv[2]));
  s.Start(handler);
  return 0;
}
客户端代码:

client.cc

#include<iostream>
#include"tcp_client.hpp"
using namespace std;

int main(int argc, char* argv[])
{
  if(argc != 3){
    printf("请输入[ip] [port]\n");
    return 0;
  }
  TcpClient c(argv[1],atoi(argv[2]));
  c.Connect();
  while(1)
  {
    string msg;
    cout<<"请输入查询单词:"<<flush;
    cin>>msg;
    c.Send(msg);
    string mmm;
    c.Recv(&mmm);
    cout<<"server: "<<mmm<<endl;
  }
  return 0;
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值