CANoe编程实例--TCP/IP通信

news2024/11/16 17:48:09

1、简介

       本实例将使用目前常用的开发工具C#来开发服务器端,以CANoe端作为客户端。服务器端和客户端,通过TCP/IP连接,实现数据交换。
       首先在服务器端建立一个监听Socket,自动创建一个监听线程,随时监听是否有客户端的连接。它只起到监听作用,当监听线程监听到客户端请求时,监听线程就调用Socket上的消息响应函数OnAccept,接收客户端的连接请求。服务器为每一个客户端请求建立一个Socket,以便并行建立消息响应,服务器端为了接收数据,必须为客户端建立消息响应函数OnReceive,用于接收数据。客户端为了接收服务器端的数据,需要在连接的Socket上建立一个消息响应函数OnReceive,用来接收数据。

2、C# TCP/IP服务器端开发

      在Visual Studio 开发环境中利用C#开发一个TCP/IP服务器端程序。

2.1、新建工程

       在Visual Studio 开发环境中,单击“文件”→“新建”→“项目”进入“新建项目”对话框。在Visual C#下面选择模板“Windows窗体应用程序”新建一个工程,并将项目命名为TCP_Demo,如图所示。

2.2、界面设计

2.2.1、控件属性列表

2.2.2、最终界面

2.3、C#代码实现

      由于程序需要使用多线程监听客户端是否接入,以及接收客户端的数据,本程序除了要添加System.NET.Sockets外,还要需要添加System.Threading。以下为C#完整代码。

using System;
using System.Windows.Forms;
using System.Net;
using System.Text;
using System.Threading;
using System.Net.Sockets;
using System.ComponentModel;

namespace TCP_Demo
{
    public partial class Form1 : Form
    {
        //定义一个TcpClient类
        static TcpClient client = null;         
        //定义一个NetworkStream类, 用于网络访问的基础流的数据操作
        static NetworkStream stream = null;
        //定义一个TcpServer类
        TcpListener server = null;
        //线程用于实时监测client是否接入,以及是否数据传过来
        public Thread SocketWatch; 
        delegate void SetTextCallback(string text);

        //0 - 断开状态; 1- 尝试连接中; 2- 已连接;3- 尝试断开中;
        public int socket_status = 0;
        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            //获取本地计算机的主机名
            string name = Dns.GetHostName();
            //获取本地计算机的Internet协议(IP)地址
            IPAddress[] ipadrlist = Dns.GetHostAddresses(name); 
            foreach (IPAddress ipa in ipadrlist)
            {
                //检索IPv4的IP地址
                if (ipa.AddressFamily == AddressFamily.InterNetwork)
                {
                    lstShow.Items.Add("检索到主机的IP地址:" + ipa.ToString());
                    //将第一个有效的IPv4地址作为服务器地址
                    if (txtServerIP.Text == "") 
                        txtServerIP.Text = ipa.ToString();
                }
            }
            btnSend.Enabled = false;
            btnEnd.Enabled = false;
        }

        private void btnStart_Click(object sender, EventArgs e)
        {
            btnStart.Enabled = false;
            int port = Convert.ToInt32(txtServerPort.Text);
            IPAddress IP = System.Net.IPAddress.Parse(txtServerIP.Text);
            IPEndPoint p = new IPEndPoint(IP, port);
            server = new TcpListener(p);
            server.Start();
            lstShow.Items.Add("服务器已启动!");
            lstShow.Items.Add("等待客户端连接....");
            Update();
            socket_status = 1; //等待client接入
            //开启新的线程,用于监控client接入和数据接收
            this.SocketWatch = new Thread(new ThreadStart(this.SocketTask));
            this.SocketWatch.Start();

            btnSend.Enabled = true;
            btnEnd.Enabled = true;

        }

        private void btnSend_Click(object sender, EventArgs e)
        {
            byte[] sendmsg = new byte[512]; //定义发送的Byte数组
            int i = 0;
            //Encode转换为UTF8
            byte[] msg = Encoding.UTF8.GetBytes(txtSend.Text);
            for (i = 0; i < msg.Length;i++ )
            {
               sendmsg[i] = msg[i];
            }
            //CANoe根据最后字符是否为'\0'来判断接收的字符串长度
            sendmsg[msg.Length] = 0x00; 
            stream = client.GetStream();
            stream.Write(sendmsg, 0, sendmsg.Length);
            lstShow.Items.Add("发送数据成功!");
        }

        private void btnEnd_Click(object sender, EventArgs e)
        {
            if (this.SocketWatch != null) this.SocketWatch.Abort();
            if (stream != null) stream.Close();
            if (client != null) client.Close();
            if (server != null) server.Stop();
            socket_status = 0;
            btnStart.Enabled = true;
            btnSend.Enabled = false;
            btnEnd.Enabled = false;

        }

        //用于实时监测client是否接入,以及是否数据传过来
        public void SocketTask()
        {
            while (true)
            {
                if (socket_status==1)
                {
                    //接受挂起的连接请求。
                    client = server.AcceptTcpClient(); 
                    socket_status = 2;
                }
                
                Byte[] bytes = new Byte[256];
                //返回用于发送和接收数据的NetworkStream
                stream = client.GetStream(); 
                try
                {
                    stream.Read(bytes, 0, bytes.Length);//从读取Stream数据
                    //按照UTF8的编码方式得到字符串
                    string data = Encoding.UTF8.GetString(bytes, 0, bytes.Length);
                    if (bytes[0] != '\0') // 如果数据是有效的
                    {
                        this.SetText(data);//数据传递给主线程
                    }
                }
                catch (System.IO.IOException)
                {
                    if (client.Connected == true)
                    {
                        client.Close(); //释放此TcpClient实例
                        stream.Close(); //关闭当前流并释放与之关联的所有资源
                    }
                    socket_status = 3;
                    break;
                }
            }
        }

        private void SetText(string text)
        {
            // InvokeRequired required compares the thread ID of the
            // calling thread to the thread ID of the creating thread.
            // If these threads are different, it returns true.
            if (this.txtReceive.InvokeRequired)
            {
                SetTextCallback d = new SetTextCallback(SetText);
                this.Invoke(d, new object[] { text });
            }
            else
            {
                this.txtReceive.Text = text;
                lstShow.Items.Add("接收到数据:" + text);
            }
        }


        private void timer1_Tick(object sender, EventArgs e)
        {
            //处理界面的更新
            Socket s;
            if (client != null)
            {
                if (socket_status ==3) //尝试断开中
                {

                    server.Stop();
                    lstShow.Items.Add("客户端已断开!");
                    txtClientIP.Text = "";
                    txtClientPort.Text = "";
                    btnStart.Enabled = true;
                    btnSend.Enabled = false;
                    btnEnd.Enabled = false;
                    client = null;
                    socket_status = 0;
                }
                else
                {
                    if (txtClientIP.Text == "")
                    {
                        lstShow.Items.Add("客户端已连接!");
                        s = client.Client;
                        //显示远程客户端IP和Port端口
                        txtClientIP.Text = s.RemoteEndPoint.ToString().Split(':')[0];
                        txtClientPort.Text = s.RemoteEndPoint.ToString().Split(':')[1];
                    }
                }

            }
        }
    }

}

3、CANoe TCP/IP客户端开发

       对于CANoe客户端的演示,本实例力求简单,同时突出TCP/IP的通信功能,在实例设计中只使用一个网络节点和一个面板。面板主要用于演示与TCP/IP服务器端的数据发送与接收。当然,读者可以将这单一功能移植到自己的仿真工程中,将服务器端传过来的字符串信息根据项目需要与仿真工程的系统变量、环境变量、信号、报文等关联起来。服务器端也可以将CANoe发送字符进行解析。这种通过TCP/IP来远程监控CANoe运行的解决方案,可以广泛应用于日常的项目中。

3.1、创建仿真工程

        在CANoe界面选择File→New,在可选的模板中选择CAN 500kBaud1ch(波特率为500kBaud,1通道)。在Simulation Setup窗口中添加一个网络节点为TcpClient,如图所示,并将其CAPL程序设定为TcpClient.can。

3.2、新建系统变量

         为了与面板上的控件关联,方便数据的传递和处理,本实例需要创建表中所列出的系统变量。

3.3、Panel设计

3.3.1、Panel属性列表

       与C#.NET程序的用户界面类似,在CANoe端也需要设计一个客户界面来与TCP/IP服务器端通信。下表为TCP/IP客户端面板的控件列表及属性设定,可以根据此列表来创建一个面板。

3.3.2、Panel最终界面

3.4、CAPL实现

       TCP/IP的CAPL实现主要通过调用CANoe提供的相关CAPL函数。为了方便调用CAPL的Socket接口,Vector提供了一个IPCommon.can头文件。

3.4.1、头文件

/*@!Encoding:1252*/
variables
{
  const long  INVALID_SOCKET =    ~0;
  const long  WSA_IO_PENDING =   997;
  const long  WSAEWOULDBLOCK = 10035;
  const dword INVALID_IP     = 0xffffffff;

  dword       gIpAddress           = INVALID_IP;
  char        gIpLastErrStr[1024]  = "";
  char        gIpAddressStr[32]    = "";
  int         gIpLastErr           = 0;

  dword       gUdpPort      = 0;
  long        gUdpSocket    = INVALID_SOCKET;
  char        gUdpRxBuffer[4096];

  dword       gTcpPort          = 0;
  long        gTcpSocket        = INVALID_SOCKET;
  long        gTcpDataSocket    = INVALID_SOCKET;
  char        gTcpRxBuffer[8192];

  // status
  int         gStatus = 0;
  const int   gkSTATUS_UNINITIALISED = 0;
  const int   gkSTATUS_INITIALISED   = 1;
}

long UdpRecv( dword socket)
{
  int result = 0;

  result = UdpReceiveFrom( socket, gUdpRxBuffer, elcount( gUdpRxBuffer));

  if ( 0 != result)
  {
    gIpLastErr = IpGetLastSocketError( socket);

    if ( WSA_IO_PENDING != gIpLastErr)
    {
      IpGetLastSocketErrorAsString( socket, gIpLastErrStr, elcount( gIpLastErrStr));

      writelineex( 0, 2, "UdpReceive error (%d): %s", gIpLastErr, gIpLastErrStr);
    }
  }

  return result;
}

long TcpRecv( dword socket)
{
  int result = 0;
  
  result = TcpReceive( socket, gTcpRxBuffer,elcount( gTcpRxBuffer));
  if ( 0 != result)
  {
    gIpLastErr = IpGetLastSocketError( socket);

    if ( WSA_IO_PENDING != gIpLastErr)
    {
      IpGetLastSocketErrorAsString( socket, gIpLastErrStr, elcount( gIpLastErrStr));

      writelineex( 0, 2, "TcpReceive error (%d): %s", gIpLastErr, gIpLastErrStr);
    }
  }

  return result;
}

3.4.2、主程序

       在TcpClient.can中,CANoe作为客户端实现检索本机IP,并处理TCP/IP的连接、数据发送、数据接收及连接断开等操作。

/*@!Encoding:1252*/
includes
{
  #include "IPCommon.can"
}

variables
{
}

void SetupIp()
{
  int   adapterIndex = 1;
  char  text[512] = "";
  char  info[512] = "";
  int   size = 512;
  long  result = 0;
  dword addresses[1];

  writeClear(0);

  if (1 > IpGetAdapterCount())
  {
    writelineex(0, 3, "Error: There is no network interface available!");
    
    stop();
  }
  IpGetAdapterDescription(adapterIndex, text, size);
  if (0 != IpGetAdapterAddress(adapterIndex, addresses, 1))
  {
    //try to check the 2nd interface
    adapterIndex ++;
    if (0 != IpGetAdapterAddress(adapterIndex, addresses, 1))
    {
    writelineex(0, 3, "Error: Could not retrieve ip address!");
    stop();
    }
  }

  gIpAddress = addresses[0]; // the interface used

  if (INVALID_IP == gIpAddress)
  {
    writelineex(0, 3, "Error: ip address to be used is invalid!");
    
    stop();
  }
 
  IpGetAdapterDescription(adapterIndex, text, size);
  snprintf(info, size, "Interface: %s", text);
  writelineex(0, 1, info);

  IpGetAdapterAddressAsString(adapterIndex, text, size);
  snprintf(info, size, "Ip address: %s", text);
  writelineex(0, 1, info);

  SysSetVariableString(sysvar::TCPIP::TcpClientIp, text);

  
  IpGetAdapterMaskAsString(adapterIndex, text, size);
  snprintf(info, size, "Subnet mask: %s", text);
  writelineex(0, 1, info);

  IpGetAdapterGatewayAsString(adapterIndex, text, size);
  snprintf(info, size, "Gateway address: %s", text);
  writelineex(0, 1, info);
  
  @TCPIP::TcpClientPort=6566;
  @TCPIP::TcpServerPort =6565;
  
  gStatus = gkSTATUS_INITIALISED;
}

on start
{
  SetupIp();  
}

on stopMeasurement
{
  ResetIp();
}

void OnTcpReceive( dword socket, long result, dword address, dword port, char buffer[], dword size)
{
  char  addressString[64] = "";

  if ( gTcpDataSocket != socket)
  {
    writelineex(0, 2, "OnTcpReceive called for unknown socket 0x%X", socket);

    return;
  }

  if (0 != result)
  {
    IpGetLastSocketErrorAsString( socket, gIpLastErrStr, elcount( gIpLastErrStr));

    writelineex( 0, 2, "OnTcpReceive error (%d): %s", IpGetLastSocketError( socket), gIpLastErrStr);

    return;
  }
 
  IpGetAddressAsString(address, addressString, elcount(addressString));

  SysSetVariableString(sysvar::TCPIP::TcpData, buffer);
  TcpRecv( socket);
}

void OnTcpSend( dword socket, long result, char buffer[], dword size)
{
  if ( gTcpDataSocket != socket)
  {
    writelineex(0, 2, "OnTcpSend called for unknown socket 0x%X", socket);
  }

  if (0 != result)
  {
    IpGetLastSocketErrorAsString( socket, gIpLastErrStr, elcount( gIpLastErrStr));

    writelineex( 0, 2, "OnTcpSend error (%d): %s", IpGetLastSocketError( socket), gIpLastErrStr);
  }
}

void ConnectTcp()
{ 
  char buffer[64];
  dword serverIp;

  SysGetVariableString(sysvar::TCPIP::TcpServerIp, buffer, elcount(buffer));

  serverIp = IpGetAddressAsNumber(buffer);

  if (INVALID_IP == serverIp)
  {
    writelineex(0, 1, "Error: invalid server Ip address!");
    
    return;
  }

  gTcpPort = @sysvar::TCPIP::TcpClientPort;
  
  gTcpDataSocket = TcpOpen(gIpAddress, gTcpPort);

  if ( INVALID_SOCKET == gTcpDataSocket)
  {
    writelineex(0, 1, "Error: could not open Tcp socket!");

    return;
  }
  else
  {
    writelineex(0, 1, "Tcp socket opened.");
  }

  if (0 == TcpConnect(gTcpDataSocket, serverIp, @sysvar::TCPIP::TcpServerPort))
  {
    writelineex(0, 1, "Successfully connected to server %s:%d", buffer, @sysvar::TCPIP::TcpServerPort);

    TcpRecv( gTcpDataSocket);
  }
}

void DisconnectTcp()
{
  if (INVALID_SOCKET != gTcpDataSocket)
  {
    TcpClose(gTcpDataSocket);
    
    gTcpDataSocket = INVALID_SOCKET;
  }

  writelineex(0, 1, "Tcp socket is closed.");
}

void SendTcpData()
{
  char buffer[8192];
  
  SysGetVariableString(sysvar::TCPIP::TcpClientData, buffer, elcount(buffer));

  if (INVALID_SOCKET == gTcpDataSocket)
  {
    writelineex( 0, 2, "Tcp socket is invalid!");

    return;
  }
  
  if (0 != TcpSend( gTcpDataSocket, buffer, elcount(buffer)))
  {
    gIpLastErr = IpGetLastSocketError( gTcpDataSocket);

    if ( WSA_IO_PENDING != gIpLastErr)
    {
      IpGetLastSocketErrorAsString( gTcpDataSocket, gIpLastErrStr, elcount( gIpLastErrStr));

      writelineex( 0, 2, "Tcp send error (%d): %s", gIpLastErr, gIpLastErrStr);
    }
  }
  else
  {
    writelineex( 0, 1, "Tcp data sent successfully!");
  }
}
void ResetIp()
{
  if (INVALID_SOCKET != gTcpDataSocket)
  {
    TcpClose(gTcpDataSocket);
    
    gTcpDataSocket = INVALID_SOCKET;
  }

  if (INVALID_SOCKET != gUdpSocket)
  {
    UdpClose(gUdpSocket);
    
    gUdpSocket = INVALID_SOCKET;
  }

}

void OnTcpConnect( dword socket, long result)
{
  if ( gTcpDataSocket != socket)
  {
    writelineex(0, 2, "OnTcpConnect called for unknown socket 0x%X", socket);

    return;
  }

  if (0 != result)
  {
    IpGetLastSocketErrorAsString( socket, gIpLastErrStr, elcount( gIpLastErrStr));

    writelineex( 0, 2, "OnTcpConnect error (%d): %s", IpGetLastSocketError( socket), gIpLastErrStr);

    return;
  }
  else
  {
    writelineex(0, 1, "Successfully connected to server via Tcp");

    TcpRecv( socket);
  }
}

on sysvar_update sysvar::TCPIP::TcpConnect
{
  if (@this)
  {
    ConnectTcp();
  }
}

on sysvar_update sysvar::TCPIP::TcpDisconnect
{
  if (@this)
  {
    DisconnectTcp();
  }
}

on sysvar_update sysvar::TCPIP::TcpSend
{
  if (@this)
  {
    SendTcpData();
  }
}

4、运行测试

       先运行TCP/IP服务器端应用,服务器的IP地址为本机的IP地址,端口6565是程序的默认端口,也可以输入一个其他的端口号。单击“开始”按钮,服务器端应用将进入接入监听状态。

        这时运行CANoe的Tcp_Client仿真工程,Client Panel的客户端IP地址也将自动设置为本机的IP地址,端口6566为默认端口,读者也可修改该端口号。在服务器IP地址栏和端口栏可以输入对应的服务器IP和端口。单击Connect to server按钮,服务器端将收到接入请求,这时服务器端将显示来自客户端的IP信息和端口号。成功连接以后,服务器端和客户端之间可以相互发送信息。

        作为演示,可以允许服务器端应用和CANoe仿真工程运行在同一台计算机上,图为同一台计算机上演示TCP服务器端与客户端之间通信的效果图。

       这里需要指出的是,为了演示方便,CANoe例程中采用自动识别IP地址,如果使用的计算机上有多个网络接口或蓝牙接口,建议在测试过程中将没有使用到的硬件禁掉,否则CANoe可能无法找到有效的IP地址。当然,也可以修改CANoe端的代码,去除自动识别本机IP地址的功能。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1956336.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

使用 Visual Studio 2022 自带的 cl.exe 编译 tensorRT自带测试样例 sampleOnnxMNIST

1. 新建任意文件夹&#xff0c;将 D:\install\tensorRT\TensorRT-8.6.1.6\samples\sampleOnnxMNIST 下面的 sampleOnnxMNIST.cpp 文件复制进来&#xff0c;同时 D:\install\tensorRT\TensorRT-8.6.1.6\samples\sampleOnnxMNIST 下面的 sample_onnx_mnist.vcxproj 中的内容&…

WEBKIT 通过JavaScript 调用本地,硬件未来之窗OS硬件APP

以酒店为例我们需要调用shen份证读取&#xff0c;采集人脸&#xff0c;门锁写房卡&#xff0c;如何通过浏览器调用 1.通过本地http服务 2.通过webkit模式 这里说政务单位模式的集成 由于篇幅问题&#xff0c;怎么集成webkit就不说了 一、webkkit加载交互本地代码 browser.…

【Kettle实现神通(数据库)MPP增量、全量数据ETL,同步任务Linux运行(通用)】

1、背景介绍 具体Kettle操作步骤不做过多介绍&#xff0c;主要技术方案说明&#xff0c;Kettle8.2版本放在底部链接提取&#xff0c;本次采用Kettle实现源端&#xff1a;神通数据通用库、目标端&#xff1a;神通MPP增量数据同步&#xff0c;并在服务器端运行Job。 2、windows…

Materials Today|用于婴儿监护的柔性电子设备 (柔性健康监测/柔性传感/可穿戴电子/电子皮肤/柔性电子)

西安交通大学方云生&#xff08;Yunsheng Fang&#xff09;、徐峰&#xff08;Feng Xu&#xff09;和西安交通大学第一附属医院林婷&#xff08;Ting Lin&#xff09;团队&#xff0c;在期刊《Materials Today》上发布了一篇题为“Soft electronics for advanced infant monito…

关于@JsonSerialize序列化与@JsonDeserialize反序列化注解的使用(密码加密与解密举例)

注&#xff1a;另一种方式参考 关于TableField中TypeHandler属性&#xff0c;自定义的类型处理器的使用&#xff08;密码加密与解密举例&#xff09;http://t.csdnimg.cn/NZy4G 1.简介 1.1 序列化与反序列化 学习注解之前&#xff0c;我们可以先了解一下什么是序列化与反序列…

JAVA里的配置文件(Properties)详解

package Properties;import java.util.Map; import java.util.Properties; import java.util.Set;public class demo1 {public static void main(String[] args) {/*Properties作为Map集合的操作*///1.创建集合的对象Properties pnew Properties();//2.添加数据//细节&#xff…

谷粒商城实战笔记-79-商品服务-API-平台属性-销售属性维护

文章目录 一&#xff0c;列表接口开发1&#xff0c;新建常量类2&#xff0c;路径参数识别规格参数和销售属性 二&#xff0c;其他接口三&#xff0c;编码经验-使用常量类为什么要用常量类&#xff1f;示例 这一节的主要内容是&#xff1a; 销售属性列表查询接口的开发将代码中的…

C++ 沙漏图案(Hour-glass Pattern)

给定正整数 n&#xff0c;以沙漏形式打印数字模式。示例&#xff1a; 输入&#xff1a;rows_no 7 输出&#xff1a; 1 2 3 4 5 6 7 2 3 4 5 6 7 3 4 5 6 7 4 5 6 7 5 6 7 6 7 7 6 7 5 6 7 4 5 6 7 3 4 5 6 7 2 3 4 5 6 7 1 2 3 4 5 6…

等保2.0测评 — 容器测评对象选取

之前有小伙伴提问到&#xff0c;关于容器到底要测评哪些内容&#xff0c;也就是测评对象的选取。 首先要区分的是容器与容器集群这两个概念。容器集群概念可参考该篇文章。 不使用容器扩展要求情况 当仅使用容器技术时&#xff0c;采用安全通用要求&#xff0c;无需使用容器…

AFSim仿真系统-架构概览

引言 本文档从最终用户的角度描述了AFSIM架构&#xff0c;旨在帮助最终用户深入了解AFSIM的操作概念。 核心架构 AFSIM基于面向对象的C架构&#xff0c;提供了一种可扩展和模块化的架构&#xff0c;使得许多附加功能能够轻松集成。AFSIM允许新的组件模型&#xff08;如传感器、…

2019数字经济公测大赛-VMware逃逸

文章目录 环境搭建漏洞点exp 环境搭建 ubuntu :18.04.01vmware: VMware-Workstation-Full-15.5.0-14665864.x86_64.bundle 这里环境搭不成功。。patch过后就报错&#xff0c;不知道咋搞 发现可能是IDA加载后的patch似乎不行对原来的patch可能有影响&#xff0c;重新下了patch&…

LiteFlow条件组件的设计组件标签|组件参数,EL与或非表达式正反解析,元数据管理

个人博客&#xff1a;无奈何杨&#xff08;wnhyang&#xff09; 个人语雀&#xff1a;wnhyang 共享语雀&#xff1a;在线知识共享 Github&#xff1a;wnhyang - Overview 参考 https://juejin.cn/post/7005869798483558431 &#x1f349;组件参数 | LiteFlow &#x1f34…

黑龙江等保测评如何做到既全面又高效?

在黑龙江省进行等保测评&#xff0c;必须在全面和高效之间寻求一个平衡点&#xff0c;以保证网络的安全性和可靠性。黑龙江等保测评怎样才能在二者之间发现黄金交汇点&#xff1f;下面&#xff0c;我们来揭开谜底。 精准定位&#xff0c;明确测评范围 首先&#xff0c;一个综…

LLaMA Factory添加新模型template的实战解析

大家好,我是herosunly。985院校硕士毕业,现担任算法研究员一职,热衷于大模型算法的研究与应用。曾担任百度千帆大模型比赛、BPAA算法大赛评委,编写微软OpenAI考试认证指导手册。曾获得阿里云天池比赛第一名,CCF比赛第二名,科大讯飞比赛第三名。授权多项发明专利。对机器学…

OpenCV facedetect 人脸检测官方示例项目配置

运行程序。该程序会自动打开摄像头&#xff0c;识别并定位摄像头前的人脸以及眼睛部位。 输入q或者Q&#xff0c;退出程序。 或进行文本中所包含的图片路径 或 单个图片进行检测&#xff0c;自行修改代码即可 配置环境项目&#xff0c;debug 解决error C4996: ‘fopen’: This…

python 可视化探索(一):基础图表

总结&#xff1a;本文为和鲸python 可视化探索训练营资料整理而来&#xff0c;加入了自己的理解&#xff08;by GPT4o&#xff09; 原作者&#xff1a;作者&#xff1a;大话数据分析&#xff0c;知乎、公众号【大话数据分析】主理人&#xff0c;5年数据分析经验&#xff0c;前…

六、Spring Boot - 上手篇(2)

&#x1f33b;&#x1f33b;目录 一、SpringBoot 构建RESTful API1.1 RESTful介绍1.2 RESTful接口设计1.3 用户实体bean创建 User1.4 创建Controller UserController1.5 Postman 测试RESTful 接口 二、SpringBoot 使用Swagger2 构建API文档2.1 Swagger2介绍2.2 SpringBoot 开启…

2020年 - 2022年 上市公司-劳动投资效率数据(原始数据、代码do文件、参考文献、最终结果)

劳动投资效率概述 劳动投资效率是衡量企业在人力资源管理方面效果和效率的关键指标。它关注企业在劳动力投资上的效益&#xff0c;即企业对于人力资源的投入与产出之间的比率。这一指标对于评估企业的人力资源管理策略及其对企业绩效的影响至关重要。 劳动投资效率的测度指标…

【Golang 面试 - 基础题】每日 5 题(八)

✍个人博客&#xff1a;Pandaconda-CSDN博客 &#x1f4e3;专栏地址&#xff1a;http://t.csdnimg.cn/UWz06 &#x1f4da;专栏简介&#xff1a;在这个专栏中&#xff0c;我将会分享 Golang 面试中常见的面试题给大家~ ❤️如果有收获的话&#xff0c;欢迎点赞&#x1f44d;收藏…

Redis快速入门基础

Redis入门 Redis是一个基于内存的 key-value 结构数据库。mysql是二维表的接口数据库 优点&#xff1a; 基于内存存储&#xff0c;读写性能高 适合存储热点数据(热点商品、资讯、新闻) 企业应用广泛 官网:https://redis.io 中文网:https://www.redis.net.cn/ Redis下载与…