TCP服务器端、客户端通讯(赋源码)

2023-05-16

实现通讯,我们首先要知道是怎么样的一个流程,下图是我画的一个通讯流程图:

一.Linux服务器端

我是在Ubuntu20.04下进行的,使用的是C++,引入头文件socket.h

  1. socket()

创建一个socket套接字,使用socket()函数。我们可以定义一个int类型用于接收返回值,来判断socket是否建立成功

int socket_fd = socekt(AF_INET, SOCK_STREAM, 0);

若建立失败,返回-1

  1. sockaddr_in结构体

创建一个sockaddr_in结构体,存储网络地址(IP,Port)

struct sockaddr_in local_addr;
local_addr.sin_family = AF_INET;
local_addr.sin_port = htons(端口号);
local_addr.sin_addr.s_addr = inet_addr("IP地址");
  1. bind()

使用bind()函数绑定套接字。若绑定失败,返回-1。

int Bind = bind(socket_fd,(struct sockaddr *)&local_addr, sizeof(local_addr));
  1. listen()

设置监听,该函数最后一个值是最大连接数

listen(socket_fd,10);
  1. accept()

与客户端建立连接。建立失败,则返回-1。

该函数会起到一个阻塞作用,直到有客户端连接,该函数才执行通过,否则一直处于等待、阻塞状态

int client_fd = accept(socket_fd,(struct sockaddr *)&client_addr,&len)
  1. read()/recv()

用来接收客户端消息,recv()比read()多一个参数,可以指定标志来控制如何接收数据,若为0,则二者一样。

二者的具体区别,这篇文章说的挺详细的:https://blog.csdn.net/hhhlizhao/article/details/73912578

int Recv = recv(client_fd,recvBuf,sizeof(recvBuf),0);
  1. write()/send()

给客户端发送消息

二者区别,可以参考:https://blog.csdn.net/qq_40443457/article/details/104250998

https://blog.csdn.net/baidu_15547923/article/details/90206381

send(client_fd,message,sizeof(message),0);
int Write = write(client_fd,sendBuf,strlen(sendBuf));
  1. close()

关闭客户端

close(client_fd);
close(socket_fd);
  1. 工程源码

#include <iostream>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
using namespace std;
#define message "The server is ready!"
#define SendBuf "Server Received!"

int socket_fd;
int client_fd;
int queryCount = 1; //查询次数
char recvBuf[1024]={0}; //接收
int BuildSock()
{
    //1.创建一个socket套接字
    socket_fd = socket(AF_INET,SOCK_STREAM,0);
    if (socket_fd == -1)
    {
        cout << "Socket Error!" << endl;
        exit(-1);
    }
    cout << "Socket Ready!" << endl;

    //2.sockaddr_in结构体:可以存储一套网络地址(包括IP与端口),此处存储本机IP地址与本地的一个端口
    struct sockaddr_in local_addr;
    local_addr.sin_family = AF_INET;
    local_addr.sin_port = htons(端口号);  //绑定端口
    local_addr.sin_addr.s_addr = inet_addr("IP地址"); //绑定本机IP地址

    //3.bind(): 将一个网络地址与一个套接字绑定,此处将本地地址绑定到一个套接字上
    int Bind = bind(socket_fd, (struct sockaddr *)&local_addr, sizeof(local_addr)); //成功则返回0 ,失败返回-1
    if (Bind == -1)
    {
        cout << "Bind Error!" << endl;
        return -1;
    }
    cout << "Bind Ready!" << endl;
}

int ListenClient()
{    
    string strSendBuf;
    struct sockaddr_in client_addr;
    socklen_t len=sizeof(client_addr);
    
    client_fd=accept(socket_fd,(struct sockaddr *)&client_addr,&len);    //建立连接
    if (client_fd == -1)
    {
        cout<<"accept错误\n"<<endl;
        //exit(-1);
    }
    else
    {
        char *ip=inet_ntoa(client_addr.sin_addr);
        cout<<"客户端:"<<ip<<" 连接到本服务器成功!"<<endl;
        send(client_fd,message,sizeof(message),0);  //发送初始化消息

        while (true)
        {               
            int Recv = recv(client_fd,recvBuf,sizeof(recvBuf),0);   //接受来自客户端的内容
            if (Recv<0)
            {
                cout<<"未接收到客户端的请求,或客户端已断开"<<endl;
                return -1;
            }
            cout<<"*********************************"<<endl;
            cout<<"查询次数:"<<queryCount<<endl;
            cout<<"receive data: "<<recvBuf<<endl;         
            char sendBuf[99999]={0};            
            queryCount++;     
            cout<<"给客户端发送数据中..."<<endl;
            int Write = write(client_fd,sendBuf,strlen(sendBuf));
            if (Write<0)
            {
                cout << "Error: Send info to server failed !"<<endl;
                return -1;
            }
            cout<<"给客户端发送完成!"<<endl;  
            cout<<"*********************************"<<endl;
        }
        
    }
    close(client_fd);
}

int main(int argc,char *argv[])
{
    cout<<"============================="<<endl;
    cout<<"     This is the server      "<<endl;
    cout<<"============================="<<endl;
       
    BuildSock();
    listen(socket_fd,10);
    while (1)
    {
        cout<<"等待客户端的连接..."<<endl;
        ListenClient();
    }
       
    close(socket_fd);
    return 0;
}

二.Windows服务器端

引入头文件winsock2.h

  1. WSAStartup()

打开网络库

WSADATA wsd;
WSAStartup(MAKEWORD(2, 2), &wsd);
  1. socket()

创建socket套接字,和服务器端类似

int m_SockServer = socket(AF_INET, SOCK_STREAM, 0);
  1. sockaddr_in结构体

创建一个sockaddr_in结构体,存储网络地址(IP、Port)

sockaddr_in serveraddr;
serveraddr.sin_family = AF_INET;
serveraddr.sin_port = htons(端口号);
serveraddr.sin_addr.S_un.S_addr = inet_addr("IP地址");
  1. bind()

绑定套接字

bind(m_SockServer, (sockaddr*)&serveraddr, sizeof(serveraddr));
  1. listen()

设置监听

listen(m_SockServer, 0);
  1. accept()

与客户端建立连接

int len = sizeof(serveraddr);
accept(m_SockServer, (sockaddr*)&serveraddrfrom, &len);
  1. recv()

接收来自客户端的消息

recv(m_SockClient, buffer, 1024, 0);
  1. send()

给客户端发送消息

send(m_Server[iConnect], buf, sizeof(buf), 0);
  1. 释放资源

WSACleanup();

注意:write()、send()、recv()、sizeof()和strlen()的使用区别

  1. 工程源码

server.cpp:

#define _CRT_SECURE_NO_WARNINGS
#define _WINSOCK_DEPRECATED_NO_WARNINGS
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<thread>
#include<winsock2.h>   
#include "server.h"
#include<assert.h>
#include<stdio.h>
#include<Windows.h>
#include<list>
#pragma comment(lib,"ws2_32.lib")     //链接库文件
using namespace std

char Ip[20][200] = { '\0' };
int iConnect = 0;                     //当前客户端数量
int main(void)
{
    WSADATA wsd;         //定义WSADATA对象
  
    if (WSAStartup(MAKEWORD(2, 2), &wsd)) 
    {
        printf("Initlalization Error!");
        return -1;
    }

    sockaddr_in serveraddr; //创建sockaddr_in对象储存自身信息(当有多个端口,可以多个绑定)
    serveraddr.sin_family = AF_INET;             //设置服务器地址家族
    serveraddr.sin_port = htons(端口号);           //设置服务器端口号
    serveraddr.sin_addr.S_un.S_addr = inet_addr("IP地址");    //本机既作为服务器有作为客户端的话,ip为127.0.0.1或localhost

    //int socket(int domain, int type, int protocol);协议域 socket类型 指定协议0 auto:type
    int  m_SockServer;            //创建socket对象映射 本质是int型  SOCKET    
    m_SockServer = socket(AF_INET, SOCK_STREAM, 0);    //创建一个临时变量并赋值给m_SockServer
    //std::cout << m_SockServer << std::endl;

    //int bind( int sockfd, const struct sockaddr addr, socklen_t addrlen); sockfd为socket映射参数,唯一确定一个socket
    int i = bind(m_SockServer, (sockaddr*)&serveraddr, sizeof(serveraddr));    //把映射和socket绑定
    std::cout << "bind:" << i << std::endl;//0 表示成功

    int iMaxConnect = 20;           //最大连接数
    char buf[] = "Server Connection Successful\0";
    char WarnBuf[] = "It is voer Max connect\0";

    sockaddr_in serveraddrfrom;
    int m_Server[20];      //创建socket数组来存放来自客户端的信息最大连接数为20
    while (true) 
    {
        //int listen(int sockfd, int backlog);
        //第一个参数即为要监听的socket套接字,第二个参数为相应socket可以排队的最大连接个数。
        int iLisRet = listen(m_SockServer, 0);    //进行监听
        int temp = 0;
        int Len = sizeof(serveraddrfrom);
        int len = sizeof(serveraddr);            //serveraddr所占的字节大小
        //int accept(int sockfd, struct sockaddr addr, socklen_t addrlen);
        //accept函数的第一个参数为服务器的socket描述字,第二个参数为指向struct sockaddr *的指针,用于返回客户端的协议地址,第三个参数为协议地址的长度。
        m_Server[iConnect] = accept(m_SockServer, (sockaddr*)&serveraddrfrom, &len);

        if (m_Server[iConnect] != INVALID_SOCKET)  //INVALID_SOCKET表示无效 
        {
            //int getsockname(int,struct sockaddr addr, *len) -1表示创建失败
            if (getsockname(m_Server[iConnect], (struct sockaddr*)&serveraddrfrom, &Len) != -1)
            {   // serveraddrfrom 接受到客户端的socket信息
                printf("listen address = %s:%d\n", inet_ntoa(serveraddrfrom.sin_addr), ntohs(serveraddrfrom.sin_port));
                printf(Ip[iConnect], "%s", inet_ntoa(serveraddrfrom.sin_addr));
            }
            else 
            {
                printf("getsockname error\n");
                exit(0);
            }
            //int send (int socket_id,char [],int lens,0);
            int ires = send(m_Server[iConnect], buf, sizeof(buf), 0);   //发送字符过去
            std::cout << "accept" << ires << std::endl << std::endl;    //显示已经连接次数                         
            iConnect++;//当前连接数
            if (iConnect > iMaxConnect) 
            {
                //判断连接数是否大于最大连接数 
                int ires = send(m_Server[iConnect], WarnBuf, sizeof(WarnBuf), 0);
            }
            else 
            {
                std::thread th1(test_threadpro, (void*)m_Server[--iConnect]); //启动线程
                th1.detach();
            }
        }
    }

    WSACleanup();     //用于释放ws2_32.dll动态链接库初始化时分配的资源
}

三.客户端

Windows环境下,引用头文件winsock2.h

WSAStartup()

1.打开网络库

WSADATA wsd;
WSAStartup(MAKEWORD(2, 2), &wsd);

2.socket()

创建socket套接字,和服务器端类似

SOCKET Socket;
Socket = socket(AF_INET, SOCK_STREAM, 0);

3.创建sockaddr_in结构体

创建一个sockaddr_in结构体,存储网络地址(IP、Port)

sockaddr_in SockAddr_In;
SockAddr_In.sin_family = AF_INET;   //ipv4
SockAddr_In.sin_port = htons(端口号);  //端口
SockAddr_In.sin_addr.S_un.S_addr = inet_addr("IP");    //目标服务器的IP

4.accept()

与服务器端建立连接,连接失败,返回-1

int i = accept(Socket, (sockaddr*) & SockAddr_In, sizeof(SockAddr_In));

此处接至服务器端accept()下

5.write()/send()

给服务器端发送消息

int Send = send(Socket, input, sizeof(input), 0);

注意:输入过程中,要注意:cin以空格为分隔,输入的字符串中有空格的时候,会被分开。使用cin.getline()

6.recv()/read()

接收来自服务器端的消息

receive = recv(Socket, recvbuf, sizeof(recvbuf), 0);

关闭客户端的时候,服务器端也会随之断开:注意close()的使用

7.工程源码

#define _WINSOCK_DEPRECATED_NO_WARNINGS
#include <iostream>
#include <winsock2.h>
#pragma comment(lib,"ws2_32.lib")
using namespace std;

int main()
{
    WSADATA wsd;
    WSAStartup(MAKEWORD(2, 2), &wsd);
    SOCKET Socket;
    sockaddr_in SockAddr_In;
    SockAddr_In.sin_family = AF_INET;   //ipv4
    SockAddr_In.sin_port = htons(端口号);  //端口 
    SockAddr_In.sin_addr.S_un.S_addr = inet_addr("IP");    //目标服务器的IP
    Socket = socket(AF_INET, SOCK_STREAM, 0);
    int i = connect(Socket, (sockaddr*) & SockAddr_In, sizeof(SockAddr_In));    //connect连接成功,返回0;失败返回SOCKET_ERROR
    cout << "Connection status  " << i << endl;
    if (i == -1)
    {
        cout << "连接服务器失败!" << endl;
    }

    char recvbuf[99999]; //接收到服务器端的内容
    int receive;        //服务器端接收的
    
    receive = recv(Socket, recvbuf, sizeof(recvbuf), 0);  
    if (receive > 0)
    {
        cout << "从服务器端开始接收:" << recvbuf << endl;
        while (true)
        {
            char input[1024] = {0};   //键盘输入的字符
            receive = 0;
            cout << "发送给服务器端的内容:";
            cin.getline(input, 1024);   //cin以空格为分隔,输入的字符串中有空格的时候,会被分开
            if (!strcmp(input,"exit"))  //输入exit直接退出
            {
                send(Socket, input, sizeof(input), 0);
                return 0;
            }
            int Send = send(Socket, input, sizeof(input), 0); 
            memset(recvbuf, '\0', sizeof(recvbuf));
            //cout << receive << endl;
            receive = recv(Socket, recvbuf, sizeof(recvbuf), 0);
            
            if (receive >= 0)
            {
                cout << "从服务器端接收到的内容:\n" << recvbuf << endl;
            }
        }
    }
   
}

整体运行效果图:

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

TCP服务器端、客户端通讯(赋源码) 的相关文章

  • Mysql数据库的初始密码及如何修改密码

    数据库初始密码及如何修改密码 初始密码修改密码 初始密码 可能很多小伙伴们下载安装好MySQL后 xff0c 登录时提示你输入密码 xff0c 但是自己不知道密码是什么 xff0c 用下面的方法可以帮助你快速的找到 xff1a step1
  • John 破解shadow 密码

    1 wget https www openwall com john k john 1 9 0 tar gz 2 tar xvf john 1 9 0 tar gz 3 cd john 1 9 0 src 4 make amp make c
  • LVI-SAM代码复现、调试与运行

    一 LVI SAM介绍 LVI SAM是Tixiao Shan的最新力作 xff0c Tixiao Shan是Lego loam和Lio sam的作者 xff0c LVI SAM是Tixiao Shan最新开源的基于视觉 激光 惯导里程计S
  • Intel Realsense D455深度相机的标定及使用(一)——安装librealsense SDK2.0以及realsense-ros

    一 安装Intel RealSense SDK 2 0 Intel RealSense SDK 2 0 的DKMS内核驱动包 xff08 librealsense2 dkms xff09 支持Ubuntu LTS内核版本4 4 4 8 4
  • VINS-Mono详解(1)——feature_tracker部分

    前言 视觉 IMU融合的优势 xff1a 1 视觉可以帮助IMU消除积分漂移和校正IMU的Bias xff1b 2 借助IMU可以帮助视觉系统提升输出频率 xff1b 3 IMU可帮助单目解决尺度不可观的问题 xff0c 帮助双目减少尺度上
  • Intel Realsense D455深度相机的标定及使用(二)——对内置IMU和双目相机进行标定

    标定前需先安装librealsense SDK2 0以及realsense ros xff0c 可参考教程 xff1a Intel Realsense D455深度相机的标定及使用 xff08 一 xff09 安装librealsense
  • 五、ROS学习之订阅T265里程计数据并与stm32通信

    使用ROS读出T265里程计数据 通过节点订阅t265的里程计数据1 订阅T265的里程计信息2 实现linux系统与stm32通信 xff0c 并向stm32发送里程计信息 通过节点订阅t265的里程计数据 我使用的是Kinetic版本
  • 在js文件中调用vue组件

    正常的书写一个vue组件 lt template gt lt div class 61 34 34 gt lt div gt lt template gt lt script gt export default name 39 Subscr
  • BMP180气压传感器详解与示例(STM32 附带源码)

    BMP180气压传感器详解与示例 xff08 STM32 附带源码 xff09 简介工作模式校准数值测试流程第一步 xff1a 微处理器读取校准数值第二步 xff1a 读取温度 气压初始值第三步 xff1a 计算温度 气压第四步 xff1a
  • MAX30102脉搏血氧仪和心率传感器(三)心率计算——时域法

    文章目录 前言一 算法思想二 算法详解1 阈值检测2 等待波形稳定3 FIR滤波 存入缓存区4 检测PPG信号与阈值曲线的交点5 心率计算 三 实际测试1 静止测试2 动态测试 四 总结五 获取工程源码 前言 本章介绍PPG信号的心率计算方
  • 基于51单片机的指纹密码锁设计

    目录 具体实现功能 设计介绍 单片机介绍 设计思路 资料内容 原理图 程序 仿真实现 全部资料 具体实现功能 具体功能 xff1a 本设计采用STC89C52 AT89C52 AT89S52作为主控芯片 xff0c LCD12864液晶显示
  • 基于51单片机的智能台灯设计

    具体实现功能 系统由STC89C52单片机 43 L数码管 43 光敏电阻 43 人体感应模块 43 红外接近传感器模块构成 具体功能 xff1a xff08 1 xff09 亮度不够且有人靠近时台灯自动亮 xff1b xff08 2 xf
  • pyharm快捷键说明

    官方文档 xff1a pycharm gt gt Help gt gt Keymap Reference 1 编辑 xff08 Editing xff09 Ctrl 43 Space 基本的代码完成 xff08 类 方法 属性 xff09
  • 基于51单片机超声波液位控制器设计

    具体实现功能 系统由AT89C52单片机 43 HC SR04超声波测距模块 43 LCD1602液晶屏 43 继电器 43 LED灯指示及蜂鸣器报警模块 43 按键模块 43 电源构成 具体功能 xff1a 1 由HC SR04超声波测距
  • 基于51单片机的电子密码锁设计

    目录 具体实现功能 设计背景 硬件设计 软件设计 原理图 程序 仿真实现 全部资料 具体实现功能 系统由AT89S52单片机 43 AT24C02数据存储模块 43 按键模块 43 LCD1602显示 43 报警模块等构成 具体功能 1 输
  • 基于51单片机智能热水器控制系统

    具体实现功能 系统由STC89C52单片机 43 水位检测传感器 43 DS18B20温度探头传感器 43 按键模块 43 继电器模块 43 报警及指示模块 43 LCD1602显示模块 43 电源构成 具体功能 xff1a 1 LCD16
  • 基于51单片机的火灾报警器

    具体实现功能 系统由51单片机 43 MQ 2烟雾传感 43 ADC0832模数转换芯片 43 DS18B20温度传感器 43 数码管显示 43 按键模块 43 声光报警模块构成 具体功能 xff1a 1 实时监测及显示温度值和烟雾浓度 x
  • 基于51单片机的步进电机控制系统

    具体实现功能 系统由STC89C52单片机 43 单体数码管 43 LED指示灯 43 ULN2003驱动芯片 43 DC 5V步进电机构成 具体功能 xff1a xff08 1 xff09 实现按键控制步进电机正转 反转 加速 减速 停止
  • 基于51单片机的数字时钟(万年历)

    具体实现功能 系统由STC89C52单片机 43 DS1302时钟芯片 43 按键模块 43 LCD1602显示 43 电源构成 具体功能 xff1a 1 可以显示年 月 日 时 分 秒 星期 农历 xff1b 2 按键可以设置闹钟及报警
  • 基于51单片机的排队叫号系统

    具体实现功能 系统由STC89C52单片机 43 按键模块 43 LCD1602液晶屏 43 蜂鸣器呼叫模块 43 电源构成 具体功能 xff1a 1 主机通过按键完成叫号 xff0c LCD1602液晶显示屏显示被叫的号码及服务的柜台号

随机推荐

  • 仿真设计|基于51单片机的简易抢答器

    目录 前言 具体实现功能 设计介绍 51单片机简介 设计方案 资料内容 仿真实现 xff08 protues8 7 xff09 程序 xff08 Keil5 xff09 全部资料 xff08 压缩文件 xff09 前言 全部资料包括程序 K
  • 实物设计|基于51单片机的温湿度检测报警系统

    目录 具体实现功能 xff1a 设计介绍 51单片机简介 设计方案 资料内容 原理图和PCB xff08 AD19 xff09 仿真实现 xff08 protues8 7 xff09 程序 xff08 Keil5 xff09 全部资料 xf
  • 设计分享|74LS148实现按键控制LED灯

    目录 具体实现功能 xff1a 设计介绍 51单片机简介 设计思路 设计内容 仿真图 xff08 protues8 7 xff09 程序 xff08 Keil5 xff09 具体实现功能 xff1a 74LS148实现按键控制LED灯 设计
  • 版本控制工具GIT and SVN 命令对比

    Git 安装 Debian Ubuntu OS Apt get install libcur14 gnutls dev libexppat1 dev gettext libz dev libssl dev Apt get install g
  • SUMO仿真教程(1) ——安装环境的设置(Windows 10系统)

    SUMO安装环境的设置 目录 一 SUMO下载的官方网址二 下载步骤 xff1a 三 环境设置 xff1a 1 打开设置环境变量的界面2 用户 xff08 Administrator xff09 变量设置3 系统变量设置 四 总述 一 SU
  • SUMO仿真教程(3)—— 仿真运行(net file、rou file、sumocfg file)

    文章目录 一 基本介绍 xff1a 1 简述 xff1a 二 文件说明 xff1a 1 路网文件 net xml 2 自定义编写路由文件 rou xml xff1a 3 生成运行仿真文件 sumocfg xff1a 4 进行运行仿真 xff
  • SUMO仿真教程(5) —— 使用“XML“语言自定义构建路网

    文章目录 一 简要介绍1 node file2 edge file3 lane definitions xff08 1 xff09 路段细分 xff08 2 xff09 邻近的对向车道 xff08 3 xff09 删除边或车道 4 type
  • SUMO仿真教程(7)—— 交通需求模型介绍

    文章目录 一 简要介绍 xff1a 二 方式一 xff1a 使用行程定义三 方式二 xff1a 使用交通流定义四 方式三 xff1a 使用随机流定义五 方式四 xff1a 使用OD矩阵定义六 方式五 xff1a 使用交叉口流量和转向比定义七
  • STM32 + UCOSII 操作系统(简单讲解)

    前言 这是我将UCOSII操作系统移植在STM32单片机上后进行UCOSII操作系统学习的一些笔记与理解 xff0c 此文最后会附上我自己在UCOSII操作系统下使用STM32写的ESP8266 43 onenet 43 http协议的程序
  • 地下水监测用设备 5G无线数传终端DTU

    地下水监测用设备5G无线数传终端DTU xff0c 实现地下水水位 温度 电导率 水质 孔隙压力等数据传输入库 远程采集 远程监测 曲线及报表可视化管理 地下水监测用5G无线数传终端DTU功能配置 地下水监测用5G无线数传终端负责连接前端采
  • 图解进程线程、互斥锁与信号量-看完不懂你来打我

    在上学的时候 xff0c 老师讲到进程与线程的时候可能是这样讲的 xff1a 进程是一个具有一定独立功能的程序在一个数据集上的一次动态执行的过程 xff0c 是操作系统进行资源分配和调度的一个独立单元 xff0c 是应用程序运行的载体 线程
  • MySQL最左匹配原则,道儿上兄弟都得知道的原则

    自MySQL5 5版本起 xff0c 主流的索引结构转为B 43 树 B 43 树的节点存储索引顺序是从左向右存储 xff0c 在检索匹配的时候也要满足自左向右匹配 目录 一 最左匹配原则的原理二 违背最左原则导致索引失效的情况三 查询优化
  • 在STM32下完成基于FreeRTOS的多任务简单程序

    一 为什么要学习 RTOS 在裸机系统中 xff0c 所有的程序基本都是自己写的 xff0c 所有的操作都是在一个无限的大循环里面实现 现实生活中的很多中小型的电子产品用的都是裸机系统 xff0c 而且也能够满足需求 但是为什么还要学习 R
  • 虚拟机连不上网问题及解决

    虚拟机联网主要涉及四个方面的配合 xff1a 网络和共享中心 xff08 物理机 xff09 虚拟网络编辑器 网络适配器 有线连接的更多设置 xff08 相关配置文件 xff09 网络和共享中心 xff1a 提示 xff1a 需要注意的点是
  • linux命令查看系统硬件的版本(dmidecode)

    dmidecode命令 可以让你在Linux系统下获取有关硬件方面的信息 dmidecode的作用是将DMI数据库中的信息解码 xff0c 以可读的文本方式显示 由于DMI信息可以人为修改 xff0c 因此里面的信息不一定是系统准确的信息
  • git 设置代理和取消代理

    本地开启VPN后 xff0c GIt也需要设置代理 xff0c 才能正常略过GFW xff0c 访问goole code等网站 设置如下 xff08 可复制 xff09 xff1a git config global https proxy
  • 上下文切换理解

    1 上下文的理解 上下文是指 xff0c 每次执行前 xff0c 都会使用需要依赖两个环境 xff0c 分别是CPU寄存器 xff08 cpu中容量小但是速度很快的内存 xff09 和程序计数器 xff08 cpu正在执行的程序位置或者是准
  • debian-11版本虚拟机无法登入root账号

    debian11创建虚拟机时我们设置了root账户密码 xff0c 然而在登入时却在未列出中无法登入root账户 xff0c 如图 1 我们登入普通账号 xff0c 这里不提权是无法保存文件的 enter 输入 i 进入编辑模式 在这个位置
  • 整数加减运算的二进制表示

    两位整数的加减都可看做 一个数加上另一个数 xff0c 首先我们要把数据的二进制表示转化成补码 xff0c 因为在计算机内部 xff0c 数据的加减是按补码进行运算的 A补 43 B补 61 A 43 B 补 xff08 mod 2 n 4
  • TCP服务器端、客户端通讯(赋源码)

    实现通讯 xff0c 我们首先要知道是怎么样的一个流程 xff0c 下图是我画的一个通讯流程图 xff1a 一 Linux服务器端 我是在Ubuntu20 04下进行的 xff0c 使用的是C 43 43 xff0c 引入头文件socket