应用层:自定义网络协议:序列化和反序列化,如果是TCP传输的:还要关心区分报文边界(在序列化设计的时候设计好)——粘包问题
——两个问题:粘包、序列化反序列化
1、首先想要使用TCP协议传输的网络,服务器和客户端都应该要创建自己的套接字,因为两个都要创建,所以我们把套接字封装为一个类:
封装方法:设计模式:模版方法:先写一个模版类(基类),里面有各种函数,然后再写一个派生类里面有各种方法的实现,创建对象的时候
#pragma once
#include <iostream>
#include <string>
#include <cstring>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#define Convert(addrptr) ((struct sockaddr *)addrptr)
namespace Net_Work
{
const static int defaultsockfd = -1;
const int backlog = 5;
enum
{
SocketError = 1,
BindError,
ListenError,
};
// 封装一个基类,Socket接口类
// 设计模式:模版方法类
class Socket
{
public:
virtual ~Socket() {
}
virtual void CreateSocketOrDie() = 0;
virtual void BindSocketOrDie(uint16_t port) = 0;
virtual void ListenSocketOrDie(int backlog) = 0;
virtual Socket *AcceptConnection(std::string *peerip, uint16_t *peerport) = 0;
virtual bool ConnectServer(std::string &serverip, uint16_t serverport) = 0;
virtual int GetSockFd() = 0;
virtual void SetSockFd(int sockfd) = 0;
virtual void CloseSocket() = 0;
virtual bool Recv(std::string *buffer, int size) = 0;
// TODO
public:
// 创建服务器端的套接字,并设置为监听状态监听套接字
void BuildListenSocketMethod(uint16_t port, int backlog)
{
CreateSocketOrDie();
BindSocketOrDie(port);
ListenSocketOrDie(backlog);
}
// 创建客户端的套接字,并且申请链接
bool BuildConnectSocketMethod(std::string &serverip, uint16_t serverport)
{
CreateSocketOrDie();
return ConnectServer(serverip, serverport);
}
void BuildNormalSocketMethod(int sockfd)
{
SetSockFd(sockfd);
}
};
class TcpSocket : public Socket
{
public:
TcpSocket(int sockfd = defaultsockfd) : _sockfd(sockfd)
{
}
~TcpSocket()
{
}
void CreateSocketOrDie() override // 创建套接字
{
_sockfd = ::socket(AF_INET, SOCK_STREAM, 0);
if (_sockfd < 0)
exit(SocketError);
}
void BindSocketOrDie(uint16_t port) override // 绑定套接字
{
struct sockaddr_in local;
memset(&local, 0, sizeof(local));
local