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

需要连接

相关推荐
乐维_lwops2 小时前
案例解读:大型综合性科创产业园运维监控落地实践
运维·网络·人工智能·安全·it监控·国产运维智能体
m0_715674433 小时前
政务泛监测体系能力排行:AI 重塑监测边界,治理的颗粒度革命
大数据·网络·人工智能·安全·网络安全·政务
AI 编程助手GPT4 小时前
curl 返回成功就能收文件?用本地 HTTP 验证错误页与超时
网络·网络协议·http
十碗饭吃不饱5 小时前
后端运维:网络联通、进程查询、Java服务启动脚本
java·运维·网络
流浪0015 小时前
计算机网络篇16:传输层——TCP 报头属性字段:16 位窗口大小撑起流量控制,六个标志位标识报文类型
网络协议·tcp/ip·计算机网络·urg紧急指针·tcp报头
从琳开始9897 小时前
网络原理入门(二)------OSI七层模型?TCP/IP五层(四层)模型原来是这样的
java·网络·tcp/ip·java-ee·php
Jongkhurun8 小时前
以太网的最小帧长为什么是 64 字节:从 CSMA/CD 冲突窗口推导 64 Byte
网络协议
xiaoye-duck9 小时前
《C++ 项目:手写大模型接入 SDK》ChatGPT接口设计(下):流式响应实现和测试
网络·c++·语言模型·chatgpt
梦帮科技9 小时前
意识启发式量子隧穿退火算法用于全局优化 (CITA) 完整技术指南
网络·人工智能·算法·量子计算·模拟退火算法
坤坤子吖11 小时前
Linux网络编程:UDP进阶,从字典服务器到简单聊天室
linux·服务器·网络·c++·笔记·学习