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;
 }

需要连接

相关推荐
記億揺晃着的那天8 小时前
NAS 内网域名访问为什么需要浏览器授权
网络·nginx·js·nas
chunmiao30328 小时前
DeepSeek V4-Pro 正式版上线,API 8月17日起分时调价
网络·安全
迪康Defender10 小时前
AI 重构终端安全运营:智能分析中枢 AI Insight 模块架构与落地场景深度解析
运维·网络·人工智能·其他·安全·重构·架构
0x5311 小时前
Java网络编程(二)
java·服务器·网络
微硬创新11 小时前
老旧产线改造:耐达讯自动化16路4‑20mA转PROFINET的工程实践
人工智能·网络协议·自动化·信息与通信
西安景驰电子13 小时前
《PTP精确时间协议系列》第一篇:从原理到应用,全面解读IEEE 1588
linux·运维·服务器·开发语言·网络·windows·php
Bruce_Liuxiaowei13 小时前
基于微步在线威胁情报的公网 IP 攻击迹象监测:threatbook_query 脚本全解析与 BruceSec 平台整合实践
数据库·tcp/ip·安全·网络安全·智能体
ZGi.ai13 小时前
多模型回答不稳定:路由规则与评测方法
网络·人工智能·大模型评测·多模型·模型路由·zgi·模型网关
80s77714 小时前
独享住宅IP、长效代理ip是什么?有哪些作用?
网络·网络协议·tcp/ip
IPdodo_14 小时前
静态 IP、住宅 IP 和固定出口有什么区别?开发场景选型指南
服务器·网络·网络协议·tcp/ip·代理ip