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

需要连接

相关推荐
treesforest4 小时前
平时上网留下的IP地址,到底能被查到什么?
网络·网络协议·tcp/ip·ip地址·ip查询·定位服务
多巴胺梦想家4 小时前
06 代数系统:运算背后的结构之美
网络·拓扑学
小锋学长生活大爆炸5 小时前
【福利】最新免费领取云服务器和虚拟主机攻略
网络·github
8125035336 小时前
第 60 篇:IP选项:那些被遗忘的功能
网络·tcp/ip·智能路由器
IT小盘7 小时前
04-大模型流式输出原理-SSE与Python实现
开发语言·网络·人工智能·python
网络研究院8 小时前
2026年上半年十大网络攻击和数据泄露事件
网络·安全·漏洞·风险·数据·泄露·事件
巨量HTTP9 小时前
Python爬虫动态换IP实战,彻底解决IP403封禁、限流问题(附完整代码)
爬虫·python·tcp/ip·http
我星期八休息9 小时前
网络编程—UDP与TCP
linux·运维·网络·数据库·网络协议·tcp/ip·udp
玖玥拾9 小时前
Unity 3D 笔记(十四)Unity/C# Socket 网络笔记3
服务器·网络·unity·c#
数智化管理手记10 小时前
财务大数据怎么管住资金风险?财务大数据和财务数智化到底怎么结合?
大数据·网络·数据库·人工智能·数据挖掘