linux【网络编程】TCP协议通信模拟实现、日志函数模拟、守护进程化、TCP协议通信流程、三次握手与四次挥手

这篇具有很好参考价值的文章主要介绍了linux【网络编程】TCP协议通信模拟实现、日志函数模拟、守护进程化、TCP协议通信流程、三次握手与四次挥手。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一、TCP通信简单模拟实现

Tcp通信模拟实现与Udp通信模拟实现的区别不大,一个是面向字节流,一个是面向数据报;udp协议下拿到的数据可以直接发送,tcp协议下需要创建链接,用文件描述符完成数据的读写

1.1 服务端实现

1.1.1 接口认识

1.1.1.1 listen:监听socket
#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
int listen(int sockfd, int backlog);
sockfd:创建的套接字
backlog:新连接队列的长度限制
1.1.1.2 accept:获取连接
#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
sockfd:创健的套接字,仅用于监听新链接
addr:结构体,这里说网络通信,用sockaddr_in
addrlen:结构体大小
返回值:一个新的文件描述符(套接字),这个才是和客户端通信的文件描述符

通信就用accept返回的文件描述符,面向字节流,后续都是文件操作

1.1.2 tcpServer.hpp

#pragma once
#include "logMessage.hpp"
#include <iostream>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <cstring>
#include <unistd.h>
namespace Server
{
    enum
    {
        USAGE_ERR = 1,
        SOCKET_ERR,
        BIND_ERR,
        LISTEN_ERR
    };

    using namespace std;

    static const uint16_t gport = 8080;
    static const uint16_t gbacklog = 5;
    class tcpServer
    {
    public:
        tcpServer(const uint16_t &port = gport)
            : listen_sockfd_(-1), port_(port)
        {
        }

        void InitServer()
        {
            // 1.创建socket
            listen_sockfd_ = socket(AF_INET, SOCK_STREAM, 0);
            if (listen_sockfd_ < 0)
            {
                logMessage(FATAL, "create socket error");
                exit(SOCKET_ERR);
            }
            logMessage(NORMAL, "create socket success");

            // 2.bind网络信息
            struct sockaddr_in local;
            memset(&local,0,sizeof(local));
            local.sin_family=AF_INET;
            local.sin_port=htons(port_);
            local.sin_addr.s_addr=INADDR_ANY;
            if(bind(listen_sockfd_,(struct sockaddr*)&local,sizeof(local))<0)
            {
                logMessage(FATAL,"bind socket error");
                exit(BIND_ERR);
            }

            logMessage(NORMAL,"bind socket success");
            
            //3.设置socket为监听状态
            if(listen(listen_sockfd_,gbacklog)<0)
            {
                logMessage(FATAL,"listen socket error");
                exit(LISTEN_ERR);
            }
            logMessage(NORMAL,"listen socket success");

        }
        void start()
        {
            for(; ;)
            {
                //4.server获取新链接
                struct sockaddr_in peer;
                socklen_t len=sizeof(peer);
                //sock:和客户端通信的文件描述符
                int sock=accept(listen_sockfd_,(struct sockaddr*)&peer,&len);
                if(sock<0)//没有获取新链接成功就执行下一次循环
                {
                    logMessage(FATAL,"accpect sock error");
                    continue;
                }
                logMessage(NORMAL,"accept sock success");
                std::cout<<"sock"<<sock<<endl;

                //5.通信就用sock文件描述符,面向字节流,后续都是文件操作
                /*version1*/
                serverIO(sock);
                close(sock);
            }
        }
        void serverIO(int sock)
        {
            char buffer[1024];
            while (true)
            {
                ssize_t n=read(sock,buffer,sizeof(buffer)-1);
                if(n>0)
                {
                    buffer[n]=0;
                    std::cout<<"recv message "<<buffer<<endl;
                    string outbuffer=buffer;
                    outbuffer+="server[echo]";
                    write(sock,outbuffer.c_str(),outbuffer.size());
                }
                else if(n==0)
                {
                    //客户端退出
                    logMessage(NORMAL,"client quit ,me too!!");
                    break;
                }
            }
            
        }
        ~tcpServer()
        {
        }

    private:
        int listen_sockfd_;//不负责通信,只负责监听链接,获取新链接
        uint16_t port_;
    };
}

1.1.3 tcpServer.cc

#include "tcpServer.hpp"
#include <memory>

using namespace std;
using namespace Server;
static void Usage(string proc)
{
    cout << "\nUsage:\n\t" << proc << " local_port\n\n";
}


int main(int argc,char* argv[])
{
    if(argc!=2)
    {
        Usage(argv[0]);
        exit(USAGE_ERR);
    }
    uint16_t serverport=atoi(argv[1]);
    unique_ptr<tcpServer> tsvr(new tcpServer(serverport));
    tsvr->InitServer();
    tsvr->start();
    return 0;

}

1.2 客户端实现

1.2.1 接口认识

1.2.1.1 connect:发起连接
#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
int connect(int sockfd, const struct sockaddr *addr,socklen_t addrlen);
参数与accept一样,代表的含义也一样
返回值:成功0,失败-1

1.2.2 tcpClient.hpp

#pragma once
#include <iostream>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <cstring>
#include <string>
#include <unistd.h>

namespace Client
{
    enum
    {
        USAGE_ERR = 1,
        SOCKET_ERR,
        BIND_ERR,
        LISTEN_ERR
    };
    using namespace std;
    class tcpClient
    {
    public:
        tcpClient(const string &clientip, const uint16_t &clientport)
            : clientip_(clientip), clientport_(clientport), sockfd_(-1)
        {
        }
        void InitCient()
        {
            // 1.创建socket
            sockfd_ = socket(AF_INET, SOCK_STREAM, 0);
            if (sockfd_ < 0)
            {
                std::cerr << "socket create error" << endl;
                exit(2);
            }
        }
        void run()
        {
            struct sockaddr_in server;
            memset(&server, 0, sizeof(server));
            server.sin_family = AF_INET;
            server.sin_port = htons(clientport_);
            server.sin_addr.s_addr = inet_addr(clientip_.c_str());

            // 发起链接
            if (connect(sockfd_, (struct sockaddr *)&server, sizeof(server)) != 0)
            {
                std::cerr << "connect create error" << endl;
            }
            else
            {
                string msg;
                while (true)
                {
                    cout << "Enter# ";
                    getline(cin, msg);
                    write(sockfd_, msg.c_str(), msg.size());

                    char buffer [1024];
                    ssize_t n=read(sockfd_,buffer,sizeof(buffer)-1);
                    if (n>0)
                    {
                        buffer[n]=0;
                        cout<<"Server处理后为# "<<buffer<<endl;

                    }
                    else
                    {
                        break;
                    }
                    

                }
            }
        }
        ~tcpClient() {
            if(sockfd_>=0) close(sockfd_);
        }

    private:
        int sockfd_;
        uint16_t clientport_;
        string clientip_;
    };
}

1.2.3 tcpClient.cc

#include "tcpClient.hpp"
#include <memory>
using namespace std;
using namespace Client;
static void Usage(string proc)
{
    cout << "\nUsage:\n\t" << proc << " server_ip server_port\n\n";
}


int main(int argc,char* argv[])
{
    if(argc!=3)
    {
        Usage(argv[0]);
        exit(USAGE_ERR);
    }
    uint16_t clientport=atoi(argv[2]);
    string clientip=argv[1];

    unique_ptr<tcpClient> ucli(new tcpClient(clientip,clientport));
    ucli->InitCient();
    ucli->run();
    return 0;
}

上述代码是一个单进程的版本,一个链接过来会去死循环执行serverIO,也就是说同一时间只能有一个链接过来通信,其他的链接必须阻塞等待上一个链接退出

1.3 优化方案

1.3.1 TCP网络通信----多进程版

更该tcpServer.hpp中的start函数即可,其他文件和单进程版一致

void start()
{
    logMessage(NORMAL, "Thread init success");
    for (;;)
    {
        // 4.server获取新链接
        struct sockaddr_in peer;
        socklen_t len = sizeof(peer);
        // sock:和客户端通信的文件描述符
        int sock = accept(listen_sockfd_, (struct sockaddr *)&peer, &len);
        if (sock < 0) // 没有获取新链接成功就执行下一次循环
        {
            logMessage(FATAL, "accpect sock error");
            continue;
        }
        logMessage(NORMAL, "accept sock success,get new sock:%d", sock);

        /*******************************************version2多进程版*/

        pid_t id = fork();
        if (id == 0) // 子进程
        {
            // 关闭子进程不需要的文件描述符
            close(listen_sockfd_);

            // 子进程退出,父进程回收资源,孙子进程去执行任务
            // 孙子进程成为孤儿进程,1号进程托管并回收其退出资源
            if (fork() > 0)
                exit(0); 

            // 孙子进程
            serverIO(sock);
            close(sock);//任务完成关闭文件描述符
            exit(0); 
        }
        
        // 细节:父进程必须关闭子进程的sock,避免一直被占用
        // 这里的关闭并不是完全关闭,只是引用计数减一,并不影响孙子进程
        close(sock); // 获取之后立马关闭,多次链接出现sock都一样,也可能不一样

        // 父进程,阻塞等待子进程退出
        pid_t ret = waitpid(id, nullptr, 0);
        if (ret > 0)
        {
            std::cout << "waitsuccess" << ret << endl;
        }
    }
}     
  1. 父进程必须关闭子进程的sock,避免一直被占用
    这里的关闭并不是完全关闭,只是引用计数减一,并不影响孙子进程
  2. waitpid这里不能单纯用非阻塞等待,当有多个连接到来的时候,并且有一个进程退出,父进程非阻塞等待,去执行accept,但是如果后续没有连接来了,就一直阻塞在accept,剩下的子进程就没法回收了

前面【信号】中曾说道子进程退出时会发送SIGCHLD信号,我们可以对其设置捕捉,忽略掉其行为,父进程就不需要阻塞等待了

void start()
{
    logMessage(NORMAL, "Thread init success");
   	signal(SIGCHLD,SIG_IGN);//设置信号忽略行为
    for (;;)
    {
        // 4.server获取新链接
        struct sockaddr_in peer;
        socklen_t len = sizeof(peer);
        // sock:和客户端通信的文件描述符
        int sock = accept(listen_sockfd_, (struct sockaddr *)&peer, &len);
        if (sock < 0) // 没有获取新链接成功就执行下一次循环
        {
            logMessage(FATAL, "accpect sock error");
            continue;
        }
        logMessage(NORMAL, "accept sock success,get new sock:%d", sock);

        /*******************************************version2多进程版*/

        pid_t id = fork();
        if (id == 0) // 子进程
        {
            // 关闭子进程不需要的文件描述符
            close(listen_sockfd_);
            // 子进程
            serverIO(sock);
            close(sock);//任务完成关闭文件描述符
            exit(0); 
        }
        
        // 细节:父进程必须关闭子进程的sock,避免一直被占用
        // 这里的关闭并不是完全关闭,只是引用计数减一,并不影响孙子进程
        close(sock); // 获取之后立马关闭,多次链接出现sock都一样,也可能不一样

       
    }
}     

1.3.2 TCP网络通信----多线程版

在tcpServer类外添加ThreadData类,类内修改start函数,添加threadRoutinue函数其余不变

    class tcpServer;
    class ThreadData
    {
    public:
        ThreadData(tcpServer *self, int sockfd)
            : self_(self), sockfd_(sockfd)
        {
        }

    public:
        tcpServer *self_;
        int sockfd_;
    };
    
void start()
        {
            logMessage(NORMAL, "Thread init success");
            // signal(SIGCHLD,SIG_IGN);
            for (;;)
            {
                // 4.server获取新链接
                struct sockaddr_in peer;
                socklen_t len = sizeof(peer);
                // sock:和客户端通信的文件描述符
                int sock = accept(listen_sockfd_, (struct sockaddr *)&peer, &len);
                if (sock < 0) // 没有获取新链接成功就执行下一次循环
                {
                    logMessage(FATAL, "accpect sock error");
                    continue;
                }
                logMessage(NORMAL, "accept sock success,get new sock:%d", sock);

                

                /*******************************************version3:多线程版本*/
                 pthread_t tid;
                 ThreadData* td=new ThreadData(this,sock);
                 pthread_create(&tid,nullptr,threadRoutinue,td);

                
            }
        }
        //类内调用,静态方法
         static void* threadRoutinue(void* args)
         {
             pthread_detach(pthread_self());
             ThreadData* td= static_cast<ThreadData*>(args);
             td->self_->serverIO(td->sockfd_);
             //在一个进程中的所有线程都可以访问到文件描述符表,属于共享资源,
             //一个线程所对应的fd在使用完毕后需要进行关闭。
             close(td->sockfd_);
             delete td;
             return nullptr;
         }

多进程版,多线程版,线程池版,可参考我的Gitee

二、日志函数编写

在计算机中,日志文件是记录在操作系统或其他软件运行中发生的事件或在通信软件的不同用户之间的消息的文件。记录是保持日志的行为。在最简单的情况下,消息被写入单个日志文件。

我们借助可变参数列表来模拟实现日志函数
实现格式如:[日志等级][时间][pid][message]

#pragma once
#include <iostream>
#include <string>
#include <stdarg.h>
#include <ctime>
#include <unistd.h>

//把错误信息写到指定文件

#define LOG_NORMAL "log_nrl.txt"
#define LOG_ERR "log_err.txt"



#define DEBUG   0
#define NORMAL  1
#define WARNING 2
#define ERROR   3
#define FATAL   4

//typedef char* va_list

const char * to_levelstr(int level)
{
    switch(level)
    {
        case DEBUG : return "DEBUG";
        case NORMAL: return "NORMAL";
        case WARNING: return "WARNING";
        case ERROR: return "ERROR";
        case FATAL: return "FATAL";
        default : return nullptr;
    }
}

//void logMessage(DEBUG,"sss %f %d %c",2.1,6,'h')
void logMessage(int level,const char* format,...)
{
#define NUM 1024
    char logprefix[NUM];

    //前半部分[日志等级][时间][pid]
    snprintf(logprefix,sizeof(logprefix),"[%s][%ld][%d]",to_levelstr(level),(long int)time(nullptr),getpid());

    char logcontent[NUM];
    va_list arg;
    //初始化arg为参数列表中的第一个参数的地址
    va_start(arg,format);

    //后半部分,错误信息
    //vsnprintf()函数的作用是将可变参数列表arg中的数据按照指定的格式format写入缓冲区logcontent中
    vsnprintf(logcontent,sizeof(logcontent),format,arg);  

   

//这里做了简化,实际上是一个等级一个日志文件
    FILE* log=fopen(LOG_NORMAL,"a");
    FILE* err=fopen(LOG_ERR,"a");

    if(log !=nullptr && err!=nullptr)
    {
       
        if(level==DEBUG || level==NORMAL||level==WARNING)
        {
            fprintf(log,"%s%s\n",logprefix,logcontent);
        }

        if(level==ERROR || level==FATAL)
        {
            fprintf(err,"%s%s\n",logprefix,logcontent);
        }

        fclose(log);
        fclose(err);
    }

}

三、守护进程

3.1 引入:为什么需要守护进程化

守护进程又叫精灵进程—本质孤儿进程的一种有了守护进程,上述的服务端才能变成一个真正的服务端

linux【网络编程】TCP协议通信模拟实现、日志函数模拟、守护进程化、TCP协议通信流程、三次握手与四次挥手
1.当我们使用xsell链接远端云服务器的时候,打开的页面第一个出现的就是bash命令行,这个时候我们输入sleep 10000 | sleep 20000 |sleep 30000 &就可以添加一个后台任务。

linux【网络编程】TCP协议通信模拟实现、日志函数模拟、守护进程化、TCP协议通信流程、三次握手与四次挥手
2.在命令行运行sleep 40000 | sleep 50000 |sleep 60000 &后,查看进程,发现新创建的三个进程PGID一样,属于同一个组,完成一个任务,与之前的任务同属于一个会话(SID都一样)
linux【网络编程】TCP协议通信模拟实现、日志函数模拟、守护进程化、TCP协议通信流程、三次握手与四次挥手
3.通过查看SID进程发现,是bash:会话ID是以bash命名的
linux【网络编程】TCP协议通信模拟实现、日志函数模拟、守护进程化、TCP协议通信流程、三次握手与四次挥手
4.前后台任务切换
fg + 作业编号切换指定任务到前台
ctrl+z暂停任务:bash自动切换到前台
bg +作业编号指定任务stop->run
linux【网络编程】TCP协议通信模拟实现、日志函数模拟、守护进程化、TCP协议通信流程、三次握手与四次挥手
当我们进行网络通信的时候,如果服务器关机或注销了,任务就可能会被清理,导致客户端发送的消息无响应,这显然与真正的服务器不一样,我们需要把服务任务自成会话,自成进程组,不受终端设备影响-----守护进程

3.2 进程,守护进程化

#include <unistd.h>

pid_t setsid(void);//必须是非组长调用

setsid 用于在一个新的会话中启动一个进程。在运行 setsid 命令时,所启动的进程将会脱离当前的终端会话,并在一个新的会话中运行,这样它就不会受到终端会话关闭或挂起的影响,而可以持续运行。

#pragma once
#include <unistd.h>
#include <signal.h>
#include <cstdlib>
#include <cassert>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

#define DEV "/dev/null"  //垃圾站,写进的内容全丢弃

//自建一个会话,组长就是自己,调用函数的不能是组长
//调用完毕之后成为组长
void daemonSelf(char* currPath=nullptr)
{
    //1.让调用进程忽略掉异常的信号
    //客户端已经退出,服务端再写会崩溃
    signal(SIGPIPE,SIG_IGN);

    //2.不是组长,调用setsid
    if(fork()>0) exit(0);
    
    //子进程---守护进程又叫精灵进程---本质孤儿进程
    pid_t n=setsid();
    assert(n!=-1);

    //3.守护进程是脱离终端的,关闭或重定向以前进程默认打开的文件

    //      /dev/null 垃圾站,写进的内容全丢弃
    int fd=open(DEV,O_RDWR);
    if(fd>=0)
    {
        dup2(fd,0);
        dup2(fd,1);
        dup2(fd,2);

        //012已经执行devil/null
        close(fd);
    }
    else
    {
        close(0);
        close(1);
        close(2);
    }

    //4.可选:进程执行路径发生更改
    //chdir:将进程的当前工作目录更改为 currpath 参数指定的目录
    if(!currPath) chdir(currPath);


}

在服务端初始化完毕之后,启动之前执行daemonSelf()函数,再启动服务端,查看进程就可以得到以下信息
linux【网络编程】TCP协议通信模拟实现、日志函数模拟、守护进程化、TCP协议通信流程、三次握手与四次挥手
父进程id为1证明这个进程是一个孤儿进程,而且可以发现这个进程的PID,PGID,GID都一样,这就是自成会话,自成进程组的守护进程!!!

这个时候,即便关闭终端,只要不kill掉这个进程,他就会在一直运行响应客户端

四、TCP协议通信流程

linux【网络编程】TCP协议通信模拟实现、日志函数模拟、守护进程化、TCP协议通信流程、三次握手与四次挥手
建立连接的过程:

  • 调用socket, 创建文件描述符;
  • 调用connect, 向服务器发起连接请求;
  • connect会发出SYN段并阻塞等待服务器应答; (第一次)
  • 服务器收到客户端的SYN, 会应答一个SYN-ACK段表示"同意建立连接"; (第二次)
  • 客户端收到SYN-ACK后会从connect()返回, 同时应答一个ACK段; (第三次)
    这个建立连接的过程, 通常称为 三次握手

断开连接的过程:

  • 如果客户端没有更多的请求了, 就调用close()关闭连接, 客户端会向服务器发送FIN段(第一次);
  • 此时服务器收到FIN后, 会回应一个ACK, 同时read会返回0 (第二次);
  • read返回之后, 服务器就知道客户端关闭了连接, 也调用close关闭连接, 这个时候服务器会向客户端发送一个FIN; (第三次)
  • 客户端收到FIN, 再返回一个ACK给服务器; (第四次)

4.1 三次握手与四次挥手感性认识

三次握手—建立连接:
女方对男方说想谈恋爱,男方答应并问到什么时候开始,女方说现在

四次挥手—断开连接:
比如女方对男方说离婚,男方回复离婚
同时男方反应一会觉得不行,凭什么你先对我说,我也得休了你,然后对女方说离婚,女方回复离婚

TCP三握四挥传送门>>>文章来源地址https://www.toymoban.com/news/detail-458086.html

到了这里,关于linux【网络编程】TCP协议通信模拟实现、日志函数模拟、守护进程化、TCP协议通信流程、三次握手与四次挥手的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包赞助服务器费用

相关文章

  • 【网络编程】网络通信基础——简述TCP/IP协议

    【网络编程】网络通信基础——简述TCP/IP协议

    个人主页:兜里有颗棉花糖 欢迎 点赞👍 收藏✨ 留言✉ 加关注💓本文由 兜里有颗棉花糖 原创 收录于专栏【网络编程】【Java系列】 本专栏旨在分享学习网络编程的一点学习心得,欢迎大家在评论区交流讨论💌 ip地址简单来说就是用来描述网络上一个设备的所在位置。 端

    2024年02月04日
    浏览(16)
  • 网络编程day2——基于TCP/IP协议的网络通信

            计算机S                                                 计算机C      创建socket对象                                   创建socket对象      准备通信地址(自己的ip(非公网ip))      准备通信地址                                     (计算

    2024年02月10日
    浏览(21)
  • Java网络编程之IP,端口号,通信协议(UDP,TCP)

    Java网络编程之IP,端口号,通信协议(UDP,TCP)

    ① C/S :客户端/服务器 在用户本地需要下载安装客户端程序,在远程有一个服务器端程序。 优点:画面精美,用户体验好 缺点:用户需要下载更新 ② B/S :浏览器/服务器 只需要一个浏览器,用户通过指定网址访问对应的服务器。 优点:不需要开发客户端,只需要页面+服务

    2024年02月03日
    浏览(40)
  • 网络编程——深入理解TCP/IP协议——OSI模型和TCP/IP模型:构建网络通信的基石

    网络编程——深入理解TCP/IP协议——OSI模型和TCP/IP模型:构建网络通信的基石

    TCP/IP协议,即 传输控制协议/互联网协议 ,是一组用于在计算机网络中实现通信的协议。它由两个主要的协议组成:TCP(传输控制协议)和IP(互联网协议)。TCP负责确保数据的可靠传输,而IP则负责路由数据包以在网络中传递。TCP/IP协议簇还包含其他辅助协议,如UDP(用户数

    2024年02月14日
    浏览(12)
  • Linux 网络编程学习笔记——一、TCP/IP 协议族

    Linux 网络编程学习笔记——一、TCP/IP 协议族

    数据链路层实现了网卡接口的网络驱动程序,以处理数据在物理媒介(以太网、令牌环等)上的传输,不同的物理网络具有不同的电气特性,网络驱动程序隐藏了这些细节,为上层协议提供一个统一的接口。最常用的协议是 ARP(Address Resolve Protocol,地址解析协议)和 RARP(

    2024年02月02日
    浏览(13)
  • 【QT网络编程】实现UDP协议通信

    【QT网络编程】实现UDP协议通信

    Internet 协议集支持一个无连接的传输协议,该协议称为用户数据报协议(UDP,User Datagram Protocol)。UDP 为应用程序提供了 一种无需建立连接就可以发送封装的 IP 数据包的方法 。RFC 768 描述了 UDP。 UDP协议根据消息传送模式可以分为: 单播(Unicast)、组播(Multicast)和广播(

    2024年02月02日
    浏览(9)
  • 基于UDP/TCP的网络通信编程实现

    基于UDP/TCP的网络通信编程实现

    红色是心中永不褪色的赤诚 操作系统为网络编程提供了 Socket api , Socket是基于TCP/IP协议的网络通信的基本单元, 基于Socket的网络程序开发就是 网络编程. 由于直接与应用层联系的是传输层, 所以针对应用层协议(TCP, UDP), Shocket提供了三种套接字, 分别是 流套接字(使用TCP) , 数据报

    2024年02月08日
    浏览(15)
  • 「网络编程」第二讲:网络编程socket套接字(三)_ 简单TCP网络通信程序的实现

    「网络编程」第二讲:网络编程socket套接字(三)_ 简单TCP网络通信程序的实现

    「前言」文章是关于网络编程的socket套接字方面的,上一篇是网络编程socket套接字(二),下面开始讲解!  「归属专栏」网络编程 「主页链接」个人主页 「笔者」枫叶先生(fy) 「枫叶先生有点文青病」「每篇一句」 I do not know where to go,but I have been on the road. 我不知

    2024年02月11日
    浏览(11)
  • Linux网络编程:socket、客户端服务器端使用socket通信(TCP)

    Linux网络编程:socket、客户端服务器端使用socket通信(TCP)

    socket(套接字),用于网络中不同主机间进程的通信。 socket是一个伪文件,包含读缓冲区、写缓冲区。 socket必须成对出现。 socket可以建立主机进程间的通信,但需要协议(IPV4、IPV6等)、port端口、IP地址。          (1)创建流式socket套接字。                 a)此s

    2024年02月11日
    浏览(18)
  • linux【网络编程】之HTTPS协议,一文了解HTTPS是如何保证通信安全的

    linux【网络编程】之HTTPS协议,一文了解HTTPS是如何保证通信安全的

    在上篇文章中我们了解到什么事HTTP协议,HTTP协议内容都是按照⽂本的⽅式明⽂传输的.这就导致在传输过程中出现⼀些被篡改的情况,本期我们来探讨一下HTTPS协议。 HTTPS( 超文本传输安全协议 )也是⼀个应⽤层协议.是在HTTP协议的基础上引⼊了⼀个加密层. HTTPS:默认端口与

    2024年02月08日
    浏览(10)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包