Tcp Socket

Tcp套接字的使用和Udp套接字的使用是差不多的,但是有一些地方还是有差别的,直接上代码

cpp 复制代码
#pragma once
#include <iostream>
#include <cerrno>
#include <cstring>
#include <cstdlib>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>


std::string DefaultIp = "127.0.0.1";
int DefaultPort = 8080;
#define BACKLOG 5
class TcpSerevr
{
public:
    TcpSerevr(const std::string& Ip = DefaultIp, const int &Port = DefaultPort)
        //:_Ip(Ip)
        :_Port(Port)
        ,_ListenSockFd(-1)
        ,_IsRuning(false)
    {

    }
    void Init()
    {
        //创建套接字
        _ListenSockFd = socket(AF_INET, SOCK_STREAM, 0);
        if(_ListenSockFd < 0)
        {
            std::cout << "socket error: " << strerror(errno) << std::endl;
            exit(1);
        }
        std::cout << "Socket success" << std::endl;

        //初始化地址
        struct sockaddr_in local;
        memset(&local, 0, sizeof(local));
        local.sin_family = AF_INET;
        local.sin_port = htons(_Port);
        //local.sin_addr.s_addr = inet_addr(_Ip.c_str());
        local.sin_addr.s_addr = INADDR_ANY;
        //绑定
        int n = bind(_ListenSockFd, (const struct sockaddr*)&local, sizeof(local));
        if(n < 0)
        {
            std::cout << "bind error: " << strerror(errno) << std::endl;
            exit(1);
        }
        std::cout << "bind sucess" << std::endl;

        //设置监听
        n = listen(_ListenSockFd, BACKLOG);
        if(n < 0)
        {
            std::cout << "listen error: " << strerror(errno) << std::endl;
            exit(1);
        }
        std::cout << "listen success" << std::endl;
    }
    void HanderRequest(int SockFd)
    {
        while(true)
        {
            char Buffer[1024];
            ssize_t n = read(SockFd, Buffer, sizeof(Buffer)-1);
            if(n > 0)
            {
                Buffer[n] = 0;
                std::string EchoStr = "Server say:";
                EchoStr += Buffer;
                write(SockFd, EchoStr.c_str(), EchoStr.size());
            }
        }
    }
    void Start()
    {
        _IsRuning = true;
        while(_IsRuning)
        {
            struct sockaddr_in Src;
            socklen_t len = sizeof(Src);
            int SockFd = accept(_ListenSockFd, (struct sockaddr*)&Src, &len);
            if(SockFd < 0)
            {
                std::cout << "accept error: " << strerror(errno) << std::endl;
                continue;
            }
            std::cout << "accept sucess" << std::endl;
            HanderRequest(SockFd);
        }
        _IsRuning = false;
    }
private:
    //std::string _Ip;
    int _Port;
    int _ListenSockFd;
    bool _IsRuning;
};

Init函数

在上面的init函数中,有这样一句代码

cpp 复制代码
 //设置监听
 n = listen(_ListenSockFd, BACKLOG);
 if(n < 0)
 {
     std::cout << "listen error: " << strerror(errno) << std::endl;
     exit(1);
 }
 std::cout << "listen success" << std::endl;

因为Tcp协议是面向连接的,所以在初始化的时候需要监听

Start函数

在Start函数中,需要accept,其中,有个参数为sockfd类型的,返回值也是sockfd类型的,参数里面是用来监听的,返回的值是用为Tcp服务器服务

cpp 复制代码
struct sockaddr_in Src;
socklen_t len = sizeof(Src);
int SockFd = accept(_ListenSockFd, (struct sockaddr*)&Src, &len);

客户端函数

cpp 复制代码
#include <iostream>
#include <cstring>
#include <memory>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

int main(int argc, char *argv[])
{
    if(argc != 3)
    {
        std::cout << "Usage ./TcpClient IP Port" << std::endl;
        return 0;
    }
    std::string Ip = argv[1];
    int Port = std::atoi(argv[2]);
    int SockFd = socket(AF_INET, SOCK_STREAM, 0);
    if(SockFd < 0)
    {
        std::cout << "socket error" << std::endl;
        return 0;
    }
    std::cout << "socket sucess" << std::endl;

    struct sockaddr_in ServerAddr;
    memset(&ServerAddr, 0, sizeof(ServerAddr));
    ServerAddr.sin_family = AF_INET;
    ServerAddr.sin_port = htons(Port);
    ServerAddr.sin_addr.s_addr = inet_addr(Ip.c_str());
    
    int n = connect(SockFd, (struct sockaddr*)&ServerAddr, sizeof(ServerAddr));
    if(n < 0)
    {
        std::cout << "connect error" << std::endl;
        return 0;
    }

    while(true)
    {
        std::string Message;
        std::cout << "please send message#: ";
        std::getline(std::cin, Message);
        int n = write(SockFd, Message.c_str(), Message.size());
        if(n > 0)
        {
            char Buffer[1024];
            int m = read(SockFd, Buffer, sizeof(Buffer));
            if(m > 0)
            {
                Buffer[m] = 0;
                std::cout << Buffer << std::endl; 
            }
            else
            {
                break;
            }
        }
        else
        {
            break;
        }

    }
    close(SockFd);

    return 0;
}

客户端同样和Udp的有区别

cpp 复制代码
 int n = connect(SockFd, (struct sockaddr*)&ServerAddr, sizeof(ServerAddr));
 if(n < 0)
 {
    std::cout << "connect error" << std::endl;
    return 0;
 }

需要连接

相关推荐
虎头金猫3 天前
4K 视频总卡在公网带宽?用 N1 + OpenList 把网盘播放链路重新理顺
运维·服务器·网络·python·容器·beautifulsoup·pandas
wuyk5553 天前
《WiFi 嵌入式物联网开发全套实战》| 第 16 章 ESP32 AP+STA 双模共存原理与工程坑点
网络·stm32·物联网
XUEYUAN52123 天前
ASN 自治系统号风控:平台如何通过 IP 所属自治域批量识别代理流量
python·网络协议·http·网络安全·socks5
QYRdata3 天前
年均增速24.2%!机器人数据湖未来六年增长动能强劲
网络·机器人·服务发现
CHENKONG_CK3 天前
破解制鞋打磨痛点:RFID赋能去毛刺工序自动化升级
网络·单片机·嵌入式硬件·网络协议·tcp/ip
chshang19923 天前
工业路由器是什么?浅谈5G工业网络中的IR602
网络·物联网·5g·智能路由器
萧瑟余晖3 天前
Netty 核心组件与 Reactor 模型详解
网络·架构
ITxiaobing20233 天前
IP 定位服务选型指南:从准确率到工程落地的技术考察
linux·服务器·网络
wuyk5553 天前
【Socket 进阶之路】第 9 章 Linux 网络服务量产稳定性优化|心跳保活、TIME_WAIT、SO_LINGER、内存池、断线重连、完整异常防护框架
linux·服务器·开发语言·网络·物联网
z落落3 天前
C#UDP+串口服务端+UDP 客户端(含 CRC16 校验)
网络·网络协议·udp