【网络编程】C++实现网络通信服务器程序||计算机网络课设||Linux系统编程||TCP协议(附源码)

34 篇文章 0 订阅
订阅专栏
11 篇文章 2 订阅
订阅专栏

0000

🐍 1.程序简洁

该程序用C++实现了一个支持并发的服务器,实现了大小写转换的功能,当客户端向服务器发起链接请求时,服务器响应请求,分配资源处理任务,实现大小写的转换功能,用到的相关技术栈有:C++编程、socket套接字编程、线程池等。

🦎2. 服务端ServerTcp程序介绍

0001

在ServerTcp函数定义定义了一个init函数,用于配置服务器的网络监听套接字,绑定IP地址和端口,并开始监听来自客户端的连接请求。
①首先创建套接字:
使用 函数创建一个套接字,这里使用的是IPv4()和TCP()协议。如果创建失败,会记录错误信息并退出程序。socketPF_INETSOCK_STREAM
②绑定地址和端口:
创建一个 结构体变量 ,它用于保存服务器的本地地址信息。struct sockaddr_inlocal
2.2. 清空 结构体,然后设置其成员变量,包括地址族(,设为 表示IPv4)、端口号(,通过 将主机字节序转换为网络字节序)、IP地址(),IP地址可以是配置的服务器IP或者通配地址 。localsin_familyPF_INETsin_porthtonssin_addr.s_addrINADDR_ANY
2.3. 使用 函数将创建的套接字 与上述配置绑定。如果绑定失败,会记录错误信息并退出程序。bindlistenSock_
③监听套接字:
使用 函数将套接字设置为监听状态,同时指定了允许等待连接的队列长度为5。如果监听失败,会记录错误信息并退出程序。listen
④加载线程池:
在这里,代码通过 获取了一个线程池的单例对象,用于处理客户端的请求。这个线程池的类型是 ,这是一个自定义的任务类,它将在客户端连接时调用来处理请求。ThreadPool::getInstance()Task
最后的注释解释了程序运行到这一步时,服务器已经配置完成,等待客户端的连接请求。

0002

这段代码是服务器的主循环函数 ,它是服务器的核心部分,用于不断接受客户端的连接请求,然后将连接的处理任务交给线程池来执行。
①打开线程池:
使用 启动线程池。这个操作会让线程池中的线程开始运行,并等待任务的到来。tp_->start()
②记录线程池启动成功的日志:
使用 记录一个 DEBUG 级别的日志,表示线程池启动成功,同时记录线程池中线程的数量。
③主循环:
进入一个无限循环,用于不断接受客户端的连接请求。
④接受连接:
使用 函数等待客户端的连接请求,当有客户端连接时, 返回一个新的套接字 ,用于与客户端通信。
⑤处理连接失败:
如果 返回的套接字小于 0,表示连接失败,代码记录一个 WARNING 级别的日志,包含错误信息,然后继续等待下一个连接请求。
⑥获取客户端信息:
6.1. 获取客户端的端口号和IP地址,并进行字节序的转换,以便后续日志记录和任务处理。
6.2. 记录 DEBUG 级别的日志,表示接受到客户端的连接请求,同时包含连接信息和套接字文件描述符。
创建任务对象:
在这里,代码创建了一个 Task对象 ,这个对象用于包装客户端的套接字、IP地址、端口号以及服务处理的回调函数 。
⑦将任务加入线程池:
使用 tp_->push(t);将任务 添加到线程池中等待执行。然后不断循环

🦖3.线程池ThreadPool介绍

0004

该代码实现了一个简单的线程池类,当创建线程池实例时,调用start函数之后会创建15个线程(预先设定),当有任务通过push接口进入任务队列时,线程会执行threadRountine()函数,首先该判断该线程任务队列里有没有任务在执行,如果有,那就进行条件等待 void waitForTask() { pthread_cond_wait(&cond_, &mutex_); } ,线程池里支持15个线程同时执行处理任务的函数,当任务数超过15时才会出现等待,实现了多线程并发提高了任务执行效率.

🦕 4.任务类Task介绍

0005

‘Task’ 类的主要作用是将任务与处理该任务的函数关联起来,使任务的处理变得可定制化。当线程池从任务队列中取出任务时,会调用 ‘Task’ 对象的 ‘operator()’ 函数,进而执行与任务关联的回调函数,完成任务的处理。这种方式允许灵活地定义和执行不同类型的任务。

🐙5. 客户端Client介绍

0006

这是一个简单的客户端程序,用于与服务器建立连接并进行通信。
首先要判断运行客户端的方式必须是 接收3个参数 运行程序+ip+端口
然后绑定协议族等信息,把接收的参数封装起来,与远端的服务器发起链接请求,进行通信,当输入的内容为”quit”时退出客户端.

🦑6.运行结果:

0007

🦐 7. 源码

🦞7.1 serverTcp.cc

#include "util.hpp"
#include <signal.h>
#include <sys/types.h>
#include <sys/wait.h>
#include"Threadpool.hpp"
#include <pthread.h>
#include"Task.hpp"

 //服务函数  ---->>>小写转换大写
 void transService(int sock,const std::string &clientip,uint16_t clientPort)
    {
        assert(sock >= 0);
        assert(!clientip.empty());
        assert(clientPort >= 1024);

        char inbuffer[BUFFER_SIZE];
        while (true)
        {
             ssize_t s=read(sock,inbuffer,sizeof(inbuffer)-1); //给“\0”留一个位置
             if(s>0)
             {
                //读取成功
                inbuffer[s]='\0';
                if(strcasecmp(inbuffer,"quit")==0)
                {
                    //如果输入quit直接退出
                    logMessage(DEBUG, "client quit -- %s[%d]", clientip.c_str(), clientPort);
                    break;
                }
                logMessage(DEBUG,"trans before: %s[%d]>>>%s",clientip.c_str(),clientPort,inbuffer);
                //下面进行大小写转换 
                  for(int i = 0; i < s; i++)
                {
                    if(isalpha(inbuffer[i]) && islower(inbuffer[i])) 
                        inbuffer[i] = toupper(inbuffer[i]);
                }
                logMessage(DEBUG, "trans after: %s[%d]>>> %s", clientip.c_str(), clientPort, inbuffer);

                //把转换后的写回套接字
                write(sock, inbuffer, strlen(inbuffer));
             
             }
              else if (s == 0)
            {
                logMessage(DEBUG, "client quit -- %s[%d]", clientip.c_str(), clientPort);
                break;
            }
            else
            {
                logMessage(DEBUG, "%s[%d] - read: %s", clientip.c_str(), clientPort, strerror(errno));
                break;
            }
      
        }
          // 只要走到这里,一定是client退出了,服务到此结束
        close(sock); // 如果一个进程对应的文件fd,打开了没有被归还,文件描述符泄漏!
        logMessage(DEBUG, "server close %d done", sock);
        
    }
    
template<class T>
class ServerTcp; // 申明一下ServerTcp
template<class T>
class ThreadData
{
public:
    uint16_t clientPort_;
    std::string clinetIp_;
    int sock_;
    ServerTcp <T>*this_;
public:
        ThreadData(uint16_t port, std::string ip, int sock,  ServerTcp<T> *ts)
            : clientPort_(port), clinetIp_(ip), sock_(sock),this_(ts)
        {}
};
template<class T>
class ServerTcp
{
    public:
    //构造
    ServerTcp(uint16_t port,const std::string &ip=""):port_(port),ip_(ip),listenSock_(-1),tp_(nullptr)
    {}
    //析构
    ~ServerTcp()
    {}
    public:
    void init() //初始化函数
    {
        //1.创建套接字
        listenSock_=socket(PF_INET,SOCK_STREAM,0);   //PF_INET=IPV4 SOCK_STREAM=TCP 最后一个参数是协议 默认是0
        if (listenSock_ < 0) //如果socket创建成功会返回一个非负整数
        {
            //创建失败
            logMessage(FATAL, "socket: %s", strerror(errno));
            exit(SOCKET_ERR);
        }
        logMessage(DEBUG, "socket: %s, %d", strerror(errno), listenSock_);
        //2.bind绑定
        //2.1填充服务器信息
        struct sockaddr_in local; // 用户栈
        memset(&local, 0, sizeof local);
        local.sin_family = PF_INET;//ipv4
        local.sin_port = htons(port_);//htons 主机字节序转网络字节序
        ip_.empty()?(local.sin_addr.s_addr=INADDR_ANY):(inet_aton(ip_.c_str(),&local.sin_addr));
        //2.2本地socket信息 写入socket_t对应区域 
        if(bind(listenSock_,(const struct sockaddr*)&local,sizeof local)<0)
        {
            logMessage(FATAL,"bind:%s",strerror(errno));
            exit(BIND_ERR);
        }
        logMessage(DEBUG,"bind:%s,%d",strerror(errno),listenSock_);
        //3.监听套接字 
        if(listen(listenSock_,5)<0)
        {
            logMessage(FATAL,"listen:%s",strerror(errno));
            exit(LISTEN_ERR);
        }
        logMessage(DEBUG,"listen:%s,%d",strerror(errno),listenSock_);
        //加载线程池

        tp_=ThreadPool<Task>::getInstance();//获取单例



        //到这一步就运行起来等待客户端链接...

    }

    //多线程
   
    static void *threadRoutine(void *args)
    {
        pthread_detach(pthread_self()); //设置线程分离
        ThreadData<T> *td = static_cast<ThreadData<T>*>(args);
        td->this_->transService(td->sock_, td->clinetIp_, td->clientPort_);
        delete td;
        return nullptr;
    }


    void loop()
    {   
       //打开线程池 初始化
        tp_->start();
        logMessage(DEBUG, "thread pool start success, thread num: %d", tp_->threadNum());
      while(true)
      {
          struct sockaddr_in peer;
        socklen_t len=sizeof(peer);
        //4.获取链接
        int serviceSock=accept(listenSock_,(struct sockaddr* )&peer,&len);
        if(serviceSock<0)
        {
            //获取链接失败
            logMessage(WARINING,"Accept :%s[%d]",strerror(errno),serviceSock);
            continue;//获取失败继续获取
        }

        //4.1获取客户端基本信息
           uint16_t peerPort = ntohs(peer.sin_port);
            std::string peerIp = inet_ntoa(peer.sin_addr);

            logMessage(DEBUG, "accept: %s | %s[%d], socket fd: %d",
                       strerror(errno), peerIp.c_str(), peerPort, serviceSock);
            //5 提供服务, echo -> 小写 -> 大写
            //5.0 v0 版本 -- 单进程 -- 一旦进入transService,主执行流,就无法进行向后执行,只能提供完毕服务之后才能进行accept
            //transService(serviceSock, peerIp, peerPort);


            //多线版本
            // ThreadData *td = new ThreadData(peerPort, peerIp, serviceSock, this);
            // pthread_t tid;
            // pthread_create(&tid, nullptr, threadRoutine, (void*)td);


            //线程池
     
            Task t(serviceSock, peerIp, peerPort, transService);
        
        

            tp_->push(t);
           

      }
    }

   

    private:
        // sock
    int listenSock_;
    // port
    uint16_t port_;
    // ip
    std::string ip_;
        // 引入线程池
    ThreadPool<Task> *tp_;
};

static void Usage(std::string proc)
{
    std::cerr << "Usage:\n\t" << proc << " port ip" << std::endl;
    std::cerr << "example:\n\t" << proc << " 8080 127.0.0.1\n" << std::endl;

}

 
// ./ServerTcp local_port local_ip
int main(int argc, char *argv[])
{
    if(argc != 2 && argc != 3 )
    {
        //只能提供两个或者三个参数
        Usage(argv[0]);
        exit(USAGE_ERR);
    }
    uint16_t port = atoi(argv[1]);
    std::string ip;
    if(argc == 3) ip = argv[2];
    ServerTcp<Task> svr(port, ip);
    svr.init();
    svr.loop();
    return 0;
}

🦀 7.2 ThreadPool.hpp

#pragma once

#include <iostream>
#include <cassert>
#include <queue>
#include <memory>
#include <cstdlib>
#include <pthread.h>
#include <unistd.h>
#include <sys/prctl.h>
#include "Lock.hpp"
using namespace std;

int gThreadNum = 15; // 线程数
template <class T>
class ThreadPool
{
private:
    ThreadPool(int threadNum = gThreadNum) : threadNum_(threadNum), isStart_(false)
    {
        assert(threadNum_ > 0);
        pthread_mutex_init(&mutex_, nullptr);
        pthread_cond_init(&cond_, nullptr);
    }
    // 禁止掉拷贝构造和赋值构造
    ThreadPool(const ThreadPool<T> &) = delete;
    void operator=(const ThreadPool<T> &) = delete;

public:
    static ThreadPool<T> *getInstance()
    {
        static Mutex mutex;
        if (nullptr == instance) // 检查是否已经存在单例对象 (第一次检查)
        {
            LockGuard LockGuard(&mutex); // 进入代码块 加锁 退出
            if (nullptr == instance)     // (第二次检查)
            {
                instance = new ThreadPool<T>();
            }
            /*首先在没有锁的情况下检查一次instance是否为空,然后在加锁的情况下再进行一次检查
                确保多线程情况之下,只有一个线程成功创建实例*/
        }
        return instance;
    }

    // 线程执行函数
    static void *threadRountine(void *args)
    {
        /*每个线程将在该函数中循环等待任务,获取任务,执行任务,然后再次等待*/
        pthread_detach(pthread_self()); // 线程分离  防止资源泄漏
        ThreadPool<T> *tp = static_cast<ThreadPool<T> *>(args);
        while (1)
        {
            tp->lockQueue();
            while (!tp->haveTask())
            {
                tp->waitForTask();
            }
            // 拿到任务
            T t = tp->pop();
            tp->unlockQueue();
            t();
        }
    }

    void start()
    {
        assert(!isStart_);
        for (int i = 0; i < threadNum_; i++)
        {
            pthread_t temp;
            pthread_create(&temp, nullptr, threadRountine, this); // 创建线程
        }
        isStart_ = true; // 修改状态
    }

    void push(const T &in)
    {
        lockQueue();
        taskQueue_.push(in);
        choiceThreadForHandler();
        unlockQueue();
    }

    ~ThreadPool()
    {
        pthread_mutex_destroy(&mutex_);
        pthread_cond_destroy(&cond_);
    }

    int threadNum()
    {
        return threadNum_;
    }

private:
    void lockQueue()
    {
        pthread_mutex_lock(&mutex_);
    } // 加锁

    void unlockQueue() { pthread_mutex_unlock(&mutex_); }          // 解锁
    bool haveTask() { return !taskQueue_.empty(); }                // 判断有没有任务在执行
    void waitForTask() { pthread_cond_wait(&cond_, &mutex_); }     // 条件等待
    void choiceThreadForHandler() { pthread_cond_signal(&cond_); } // 唤醒等待
    T pop()
    {
        T temp = taskQueue_.front();
        taskQueue_.pop();
        return temp;
    }

private:
    bool isStart_;
    int threadNum_;
    queue<T> taskQueue_;    // 任务队列
    pthread_mutex_t mutex_; // 锁
    pthread_cond_t cond_;   // 条件变量
    /*条件标志的作用是在一个或多个线程
    等待某个条件成立的情况下,阻塞自己,
    直到其他线程改变了共享数据并发出
    信号告诉等待的线程可以继续执行*/

    static ThreadPool<T> *instance; // 设置单例
    // const static int a = 100;
};
template <class T>
ThreadPool<T> *ThreadPool<T>::instance = nullptr;

🐡7.3 Task.hpp

#pragma once

#include <iostream>
#include <string>
#include <functional>
#include <pthread.h>
#include "log.hpp"

class Task
{
public:
    //等价于
    // typedef std::function<void (int, std::string, uint16_t)> callback_t;
    using callback_t = std::function<void (int, std::string, uint16_t)>;
private:
    int sock_; // 给用户提供IO服务的sock
    uint16_t port_;  // client port
    std::string ip_; // client ip
    callback_t func_;  // 回调方法
public:
    Task():sock_(-1), port_(-1)
    {}
    Task(int sock, std::string ip, uint16_t port, callback_t func)
    : sock_(sock), ip_(ip), port_(port), func_(func)
    {}
    void operator () ()
    {
        logMessage(DEBUG, "线程ID[%p]处理%s:%d的请求 开始啦...",\
            pthread_self(), ip_.c_str(), port_);

        func_(sock_, ip_, port_);

        logMessage(DEBUG, "线程ID[%p]处理%s:%d的请求 结束啦...",\
            pthread_self(), ip_.c_str(), port_);
    }
    ~Task()
    {}
};

🐠7.4ClientTcp.cc

#include "util.hpp"
// 2. 需要bind吗??需要,但是不需要自己显示的bind! 不要自己bind!!!!
// 3. 需要listen吗?不需要的!
// 4. 需要accept吗?不需要的!

volatile bool quit = false;

static void Usage(std::string proc)
{
    std::cerr << "Usage:\n\t" << proc << " serverIp serverPort" << std::endl;
    std::cerr << "Example:\n\t" << proc << " 127.0.0.1 8081\n"
              << std::endl;
}
// ./clientTcp serverIp serverPort
int main(int argc, char *argv[])
{
    if (argc != 3)
    {
        Usage(argv[0]);
        exit(USAGE_ERR);
    }
    std::string serverIp = argv[1];
    uint16_t serverPort = atoi(argv[2]);

    // 1. 创建socket SOCK_STREAM
    int sock = socket(AF_INET, SOCK_STREAM, 0);
    if (sock < 0)
    {
        std::cerr << "socket: " << strerror(errno) << std::endl;
        exit(SOCKET_ERR);
    }

    // 2. connect,向服务器发起链接请求, 
    // 2.1 先填充需要连接的远端主机的基本信息
    struct sockaddr_in server;
    memset(&server, 0, sizeof(server));
    server.sin_family = AF_INET;
    server.sin_port = htons(serverPort);
    inet_aton(serverIp.c_str(), &server.sin_addr);
    // 2.2 发起请求,connect 会自动帮我们进行bind!
    if (connect(sock, (const struct sockaddr *)&server, sizeof(server)) != 0)
    {
        std::cerr << "connect: " << strerror(errno) << std::endl;
        exit(CONN_ERR);
    }
    std::cout << "info : connect success: " << sock << std::endl;

    std::string message;
    while (!quit)
    {
        message.clear();
        std::cout << "请输入你的消息>>> ";
        std::getline(std::cin, message); // 结尾不会有\n
        if (strcasecmp(message.c_str(), "quit") == 0)
            quit = true;

        ssize_t s = write(sock, message.c_str(), message.size());
        if (s > 0)
        {
            message.resize(1024);
            ssize_t s = read(sock, (char *)(message.c_str()), 1024);
            if (s > 0)
                message[s] = 0;
            std::cout << "Server Echo>>> " << message << std::endl;
        }
        else if (s <= 0)
        {
            break;
        }
    }
    close(sock);
    return 0;
}

🐟 7.5 Lock.hpp

本程序暂不涉及临界资源的访问 互斥锁的机制 可加可不加 我这里加上了 是为了学习和使用。

#pragma once
#include<iostream>
#include<pthread.h>
class Mutex
{
    public:
    Mutex()
    {
        pthread_mutex_init(&lock_,nullptr);
    }
    ~Mutex()
    {
        pthread_mutex_destroy(&lock_);
    }
       void lock()
    {
        pthread_mutex_lock(&lock_);
    }
    void unlock()
    {
        pthread_mutex_unlock(&lock_);
    }

private:
    pthread_mutex_t lock_;
};


class LockGuard
{
public:
    LockGuard(Mutex *mutex) : mutex_(mutex)
    {
        mutex_->lock();
        std::cout << "加锁成功..." << std::endl;
    }

    ~LockGuard()
    {
        mutex_->unlock();
        std::cout << "解锁成功...." << std::endl;
    }

private:
    Mutex *mutex_;
};

🐬7.7头文件util.hpp

#pragma once

#include <iostream>
#include <string>
#include <cstring>
#include <cstdlib>
#include <cassert>
#include <ctype.h>
#include <unistd.h>
#include <strings.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include "log.hpp"

#define SOCKET_ERR 1
#define BIND_ERR   2
#define LISTEN_ERR 3
#define USAGE_ERR  4
#define CONN_ERR   5

#define BUFFER_SIZE 1024

🐳7.6Makefile 文件

.PHONY:all
all:clientTcp serverTcp

clientTcp: ClientTCP.cc
	g++ -o $@ $^ -std=c++11
serverTcp:ServerTCP.cc
	g++ -o $@ $^ -std=c++11 -lpthread

.PHONY:clean
clean:
	rm -f serverTcp clientTcp

00007

🐋7.8 日志文件 log.hpp

#pragma once

#include <cstdio>
#include <ctime>
#include <cstdarg>
#include <cassert>
#include <cstring>
#include <cerrno>
#include <stdlib.h>

#define DEBUG 0
#define NOTICE 1
#define WARINING 2
#define FATAL 3

const char *log_level[]={"DEBUG", "NOTICE", "WARINING", "FATAL"};//四个提示等级

// logMessage(DEBUG, "%d", 10);
void logMessage(int level, const char *format, ...)//可变参数
{
    assert(level >= DEBUG);
    assert(level <= FATAL);

    char *name = getenv("USER");

    char logInfo[1024];//存储日志数据
    va_list ap; // ap -> char*                    va_list是一种允许您操作变量参数的类型,
    va_start(ap, format);                        //va_start用于初始化 ava_list以指向第一个变量参数

    vsnprintf(logInfo, sizeof(logInfo)-1, format, ap);

    va_end(ap); // ap = NULL


    FILE *out = (level == FATAL) ? stderr:stdout;

    fprintf(out, "%s | %u | %s | %s\n", \
        log_level[level], \
        (unsigned int)time(nullptr),\
        name == nullptr ? "unknow":name,\
        logInfo);

  
}

注:本程序是基于Linux系统下进行的,请在Linux环境下进行运行,本文为原创作品,各位转载请说明出处,创作不易,点赞支持技术大涨~~早日进大厂 ,关于程序有任何问题请在评论区留言…

🦈 🐊 🐅 🐆 🦓 🦍 🦧 🦣 🐘 🦛 🦏 🐪 🐫 🦒 🦘 🐃 🐂 🐄 🐎 🐖 🐏 🐑 🦙 🐐 🦌 🐕 🐩 🦮 🐕‍🦺 🐈 🐈‍⬛

C++tcp通讯(完整源码)
希望我的博客,能帮上你解决学习中工作中所遇到的问题
12-27 627
C++tcp通讯(完整源码)
计算机网络课程设计-网络聊天程序的设计与实现
qq_63306482的博客
01-18 946
本实验为计算机网络课程设计内容,基本上所有代码都是根据指导书给的录写出来的。有些实验需要实现图形界面,但是出于期末考试压力,我所有实验均是在控制台输入输出的,没有花额外时间去学习qt了,有精力的同学可以自学一下qt实现简单的图形界面。同时,该博客内容为部分报告内容,仅为大家提供参考,请勿直接抄袭。另外,本次实验所用平台是dev c++5.11。
[C++]C++实现本地TCP通讯的示例代码
FL1768317420的博客
02-26 453
这篇文章主要为大家详细介绍了C++如何利用TCP技术,实现本地ROS1和ROS2的通讯,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下。
C++网络通信-Socket
最新发布
IdealSanX的博客
06-06 1533
C++网络通信Socket套接字
Linuxc++实现TCP通信(详细注解)
weixin_51368286的博客
03-07 2830
c++实现TCP通信
使用 C++ 编写高并发网络服务程序模型
小桥流水 的专栏
03-25 433
使用 C++ 编写高并发网络服务程序模型
C++实现Linuxtcp网络通信
weixin_42325783的博客
02-20 480
TCP的客户端和服务端函数含义
c++路由器设置工具,支持多款路由器
11-21
路由器设置工具
QT C++语言编写的TCP网络通讯程序服务器源码
05-06
QT C++语言编写的TCP网络通讯程序服务器源码是一个非常适合初学者研究和学习网络通信技术的项目。QT是一个跨平台的应用程序开发框架,广泛应用于图形用户界面、网络编程、多媒体处理等领域。在这个项目中,我们将...
C++实现Socket编程[计算机网络实验].doc
05-09
利用C++语言,分别基于TCP和UDP编写一个简单的Client/Server网络应用程序。要求实现客户向服务器传输任意一个字符串,服务器将收到的字符串变换成大写后传回客户。修改上述程序,实现服务器根据客户请求,将服务器端...
linux网络编程,linux网络编程 pdf,C,C++
09-10
它主要涉及如何利用操作系统提供的接口,如C和C++编程语言,来实现TCP(传输控制协议)和UDP(用户数据报协议)的网络通信TCP和UDP是Internet协议栈中最常用的两种传输层协议,它们各有特点,适用于不同的应用场景...
HTTP服务端Demo(C++)
05-06
用cpprest库 写的http服务端的 例子,包括get\postd等和json数据解析; 头文件报错的话,修改工程属性中—>配置属性->VC++目录: 包含目录修改为: .\cpprest\include 库目录修改为: .\cpprest\lib\x64\release 去掉了环境变量引用。
visual c++网络编程案例实战08-09源码
04-26
网络编程是计算机科学中的一个重要领域,它允许程序通过网络进行通信,实现数据交换和服务交互。Visual C++作为微软提供的一个强大的开发环境,不仅支持桌面应用开发,还可以用来构建网络应用程序。 在"08"和"09"的...
15章基于C++从0到1手写Linux高性能网络编程框架
12-06
所以今天给大家深度讲解基于C++Linux高性能事件驱动网络编程框架的设计方法及技巧,我将采取渐进迭代的授课方式,配合C++11新特性的使用,以及网络编程理论的深度讲解,并手把手带着大家落地实现,助力在网络编程...
VC++ 实现获取路由表信息
weixin_30279751的博客
11-07 324
所谓路由表,指的是路由器或者其他互联网网络设备上存储的表,该表中存有到达特定网络终端的路径,在某些情况下,还有一些与这些路径相关的度量。 静态路由表在计算机网络中,路由表或称路由择域信息库(RIB)是一个存储在路由器或者联网计算机中的电子表格(文件)或类数据库。路由表存储着指向特定网络地址的路径(在有些情况下,还记录有路径的路由度量值)。路由表中含有网络周边的拓扑信息。路由表建立的主要目标是...
c++ 利用winpcap编制简单的路由程序_腾讯QQ升级程序存在漏洞,被利用植入后门病毒...
weixin_35940165的博客
12-24 121
近日,火绒安全团队根据用户反馈,发现一起利用腾讯QQ升级漏洞植入后门病毒的攻击事件,攻击者可利用该漏洞下发任意恶意代码。火绒团队称:截止到目前,最新版QQ(包括TIM、QQ、QQ轻聊版、QQ国际版等等)都存在该漏洞。经分析,该事件中被利用的升级漏洞曾在2015年就被公开披露过,之后腾讯对该漏洞进行修复并增加了校验逻辑。但从目前来看,QQ此处升级逻辑仍存在逻辑漏洞。另外,在排除本地劫持的可能后(LS...
什么是traceroute?Linux C/C++下利用ICMP实现traceroute
chen1415886044的博客
12-11 3241
Linux 中的 traceroute 是一个命令,它是网络工程师用来排除网络故障的最流行的工具, 它于 1987 年发明。 当您连接到网站时,您获得的数据必须沿途跨多个设备和网络传输,尤其是路由器。 跟踪路由提供了 Internet 上的数据如何从其源传输到其目的地的信息。 如何运行跟踪路由 在 Linux 系统上运行 traceroute,请执行以下操作 traceroute [hostname] 在 Windows 系统上,请执行以下操作: tracert [hostname] 术语“主
C++实现HTTP服务器 - Windows平台(开放源代码)
热门推荐
Que's C++ Studio
07-08 8万+
C++实现HTTP服务器 - Windows平台 软件名: Que's HTTP Server  (点击下载最新版含源代码) 作者: 阙荣文 - Que's C++ Studio    版权说明: 免费,开放源代码,禁止用作商业用途. 日期: 2011.7.8 1
从零开始实现一个C++高性能服务器框架----TcpServer模块
lwx666sl的博客
05-11 275
项目介绍:实现了一个基于协程的服务器框架,支持多线程、多协程协同调度;支持以异步处理的方式提高服务器性能;封装了网络相关的模块,包括socket、http、servlet等,支持快速搭建HTTP服务器或WebSokcet服务器。日志模块,使用宏实现流式输出,支持同步日志与异步日志、自定义日志格式、日志级别、多日志分离等功能。线程模块,封装pthread相关方法,封装常用的锁包括(信号量,读写锁,自旋锁等)。
使用c语言写一个使用socket跨网段通信的demo
05-03
下面是一个简单的基于socket的跨网段通信的Demo,使用C语言编写。 ```c #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <string.h> #include <arpa/inet.h> #include <sys/types.h> #include <sys/socket.h> #define PORT 8888 #define MAX_BUFFER_SIZE 1024 int main(int argc, char *argv[]) { int sockfd; struct sockaddr_in server_addr; char buffer[MAX_BUFFER_SIZE]; int ret; if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) { perror("socket"); exit(EXIT_FAILURE); } memset(&server_addr, 0, sizeof(server_addr)); server_addr.sin_family = AF_INET; server_addr.sin_port = htons(PORT); server_addr.sin_addr.s_addr = inet_addr("192.168.1.100"); if (connect(sockfd, (struct sockaddr *)&server_addr, sizeof(server_addr)) == -1) { perror("connect"); exit(EXIT_FAILURE); } while (1) { printf("Enter message: "); fgets(buffer, MAX_BUFFER_SIZE, stdin); if (send(sockfd, buffer, strlen(buffer), 0) == -1) { perror("send"); exit(EXIT_FAILURE); } if ((ret = recv(sockfd, buffer, MAX_BUFFER_SIZE - 1, 0)) == -1) { perror("recv"); exit(EXIT_FAILURE); } buffer[ret] = '\0'; printf("Received message: %s", buffer); } close(sockfd); return 0; } ``` 这个Demo实现了一个简单的客户端,可以与指定IP地址和端口号的服务器进行通信。在这个Demo中,我们使用了TCP协议进行数据传输。 在main函数中,首先创建了一个socket文件描述符,然后初始化了服务器地址结构体。在connect函数中,使用了该地址结构体来连接服务器。 然后进入了一个无限循环,每次循环中,从标准输入读取用户输入的信息,使用send函数将信息发送给服务器。然后使用recv函数接收服务器的响应,并将响应打印到标准输出中。 最后关闭了socket文件描述符,并退出程序。 需要注意的是,在实际应用中,我们需要考虑网络状况、数据的完整性、数据的安全性等问题,这里只是一个简单的Demo。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
写文章

热门文章

  • 【计算机组成原理】一文搞懂原码、反码、补码和位运算符(左移右移按位与异或等) 5668
  • C++中set使用及介绍(超详细+入门+代码解析) 5265
  • 介绍一个生成流程图工具—解放生产力 2994
  • C++智能指针-保姆级讲解带你一文搞懂智能指针(附核心代码实现+讲解) 2809
  • Linux Vim提示:E325: ATTENTION 解决方案 2789

分类专栏

  • 计算机网络 11篇
  • Mysql数据库 10篇
  • C+项目_Boost搜索引擎 4篇
  • 算法题解 19篇
  • STL专栏 4篇
  • Bug处理 5篇
  • C++基础 28篇
  • C+项目_高并发内存池 10篇
  • 编程环境设置技巧 6篇
  • Python 16篇
  • Linux 34篇
  • 计算机组成原理 2篇
  • Java 1篇
  • 数据结构 23篇
  • More Effective C++ 3篇

最新评论

  • 【Bug处理】E0265 函数 “SizeClass::RoundUp“ (已声明 所在行数:62)不可访问

    weixin_65129856: 函数设置成友元函数,不可以么

  • 【python小游戏】飞机大作战源码分享(附完整源码+图片资源可直接运行)

    2301_78632637: 大佬,从头到尾那个飞机大战该怎么运行啊表情包

  • 【计算机网络】TCP协议可靠传输保证(序列号/确认应答机制、超时重传、最长消息长度、滑动窗口控制、拥塞控制)

    CSDN-Ada助手: 不知道 网络 技能树是否可以帮到你:https://edu.csdn.net/skill/network?utm_source=AI_act_network

  • 【Bug处理】E0265 函数 “SizeClass::RoundUp“ (已声明 所在行数:62)不可访问

    Sruiy: 原来是没有加public表情包

  • 【STL】String浅拷贝问题

    2401_82793006: 哈喽比特

大家在看

  • Windows全球大范围蓝屏! CrowdStrike 安全更新问题
  • github如何实现和gitlab的同步
  • JAVA零基础小白自学日志——第十九天 539
  • [MaixCam]使用心得一:camera、display 303
  • python查看某个包的当前安装版本以及最新版本

最新文章

  • 【计算机网络】TCP协议可靠传输保证(序列号/确认应答机制、超时重传、最长消息长度、滑动窗口控制、拥塞控制)
  • 【Mysql】事务管理特性(超详细介绍事务操作、回滚、隔离级别、隔离性理解)
  • 【计算机网络经典面试题】简述 TCP 三次握手和四次挥手的过程
2024年23篇
2023年128篇
2022年14篇
2021年1篇

目录

目录

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值

PHP网站源码松岗百度关键词包年推广同乐设计网站木棉湾企业网站设计惠州优秀网站设计爱联设计网站坑梓网站优化推广沙井企业网站制作沙井模板网站建设南联百姓网标王推广双龙关键词排名包年推广坑梓网站搭建双龙百姓网标王大浪百搜标王横岗外贸网站建设福永SEO按天计费平湖品牌网站设计同乐网站制作南山关键词按天扣费木棉湾外贸网站建设坪地百度seo西乡百度网站优化荷坳百姓网标王推广同乐外贸网站制作丹竹头网站推广系统坑梓网站改版南联外贸网站建设平湖SEO按效果付费双龙网站优化按天收费大浪建网站双龙SEO按天收费歼20紧急升空逼退外机英媒称团队夜以继日筹划王妃复出草木蔓发 春山在望成都发生巨响 当地回应60岁老人炒菠菜未焯水致肾病恶化男子涉嫌走私被判11年却一天牢没坐劳斯莱斯右转逼停直行车网传落水者说“没让你救”系谣言广东通报13岁男孩性侵女童不予立案贵州小伙回应在美国卖三蹦子火了淀粉肠小王子日销售额涨超10倍有个姐真把千机伞做出来了近3万元金手镯仅含足金十克呼北高速交通事故已致14人死亡杨洋拄拐现身医院国产伟哥去年销售近13亿男子给前妻转账 现任妻子起诉要回新基金只募集到26元还是员工自购男孩疑遭霸凌 家长讨说法被踢出群充个话费竟沦为间接洗钱工具新的一天从800个哈欠开始单亲妈妈陷入热恋 14岁儿子报警#春分立蛋大挑战#中国投资客涌入日本东京买房两大学生合买彩票中奖一人不认账新加坡主帅:唯一目标击败中国队月嫂回应掌掴婴儿是在赶虫子19岁小伙救下5人后溺亡 多方发声清明节放假3天调休1天张家界的山上“长”满了韩国人?开封王婆为何火了主播靠辱骂母亲走红被批捕封号代拍被何赛飞拿着魔杖追着打阿根廷将发行1万与2万面值的纸币库克现身上海为江西彩礼“减负”的“试婚人”因自嘲式简历走红的教授更新简介殡仪馆花卉高于市场价3倍还重复用网友称在豆瓣酱里吃出老鼠头315晚会后胖东来又人满为患了网友建议重庆地铁不准乘客携带菜筐特朗普谈“凯特王妃P图照”罗斯否认插足凯特王妃婚姻青海通报栏杆断裂小学生跌落住进ICU恒大被罚41.75亿到底怎么缴湖南一县政协主席疑涉刑案被控制茶百道就改标签日期致歉王树国3次鞠躬告别西交大师生张立群任西安交通大学校长杨倩无缘巴黎奥运

PHP网站源码 XML地图 TXT地图 虚拟主机 SEO 网站制作 网站优化