【window环境、Linux环境、QT三种方法实现TCP通信】

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

文章目录

  • 前言
  • 一、Windows环境下实现TCP通信
    • 1.服务器
    • 2.客户端
    • 3.运行
  • 二、Linux环境下实现TCP通信
    • 1.服务端
    • 2.客户端
  • 三、Qt实现TCP通信
    • 1.服务端
    • 1.客户端
  • 总结


前言

大多数项目都在Linux系列的操作系统下开发服务器端,而多数客户端是在Windows平台下开发的。不仅如此,有时应用程序还需要在两个平台之间相互切换。因此,学习套接字编程的过程中,有必要兼顾Windows和Linux两大平台。另外,这两大平台下的套接字编程非常类似,如果把其中相似的部分放在一起讲解,将大大提高学习效率。只要理解好其中一个平台下的网络编程方法,就很容易通过分析差异掌握另一平台。因为不论什么方式实现,底层的逻辑都是完全一致的。


一、Windows环境下实现TCP通信

为了在Winsock基础上开发网络程序,需要做如下准备,以下两个文件都是系统自带的,包含时注意目标平台版本与库的版本一致。
导入头文件winsock2.h。
链接ws2_32.lib库(库名称和链接目录)。

1.服务器

#include <stdio.h>
#include <stdlib.h>
#include <WinSock2.h>

void ErrorHandling(char *message)
 {
	fputs(message, stderr);
	fputs("\n", stderr);
	exit(1);
}

int main(int argc, char * argv[])
 {
	WSADATA wsaData;
	SOCKET hServSock, hClntSock;
	SOCKADDR_IN servAddr, clntAddr;
	int szClntAddr;
	char message[] = "Hello World!";
	if (argc != 2) 
	{
		printf("Usage : %s <port>", argv[0]);
		exit(1);
	}

	if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
		ErrorHandling("WSAStartup() error!");

	hServSock = socket(PF_INET, SOCK_STREAM, 0);
	if (hServSock == INVALID_SOCKET)
		ErrorHandling("socket() error!");

	memset(&servAddr, 0, sizeof(servAddr));
	servAddr.sin_family = AF_INET;
	servAddr.sin_addr.s_addr = htonl(INADDR_ANY);
	servAddr.sin_port = htons(atoi(argv[1]));

	if (bind(hServSock, (SOCKADDR *)&servAddr, sizeof(servAddr)) == SOCKET_ERROR)
		ErrorHandling("bind() error!");

	if (listen(hServSock, 5) == SOCKET_ERROR)
		ErrorHandling("listen() error!");

	szClntAddr = sizeof(clntAddr);
	hClntSock = accept(hServSock, (SOCKADDR*)&clntAddr, &szClntAddr);
	if (hClntSock == INVALID_SOCKET)
		ErrorHandling("accept() error!");
	fputs("sending message...", stderr);
	fputs("", stderr);
	send(hClntSock, message, sizeof(message), 0);
	closesocket(hClntSock);
	closesocket(hServSock);
	WSACleanup();
	return 0;
}

2.客户端

#include <stdio.h>
#include <stdlib.h>
#include <WinSock2.h>
void ErrorHandling(char* message);

int main(int argc, char *argv[]) 
{
	WSADATA wsaData;
	SOCKET hSocket;
	SOCKADDR_IN servAddr;

	char message[30];
	int strlen;
	if (argc != 3) 
	{
		printf("Usage: %s <IP> <port>", argv[0]);
	exit(1);
	}

	if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
		ErrorHandling("WSAStartup() error!");

	hSocket = socket(PF_INET, SOCK_STREAM, 0);
	if (hSocket == INVALID_SOCKET)
		ErrorHandling("socket() error!");

	memset(&servAddr, 0, sizeof(servAddr));
	servAddr.sin_family = AF_INET;
	servAddr.sin_addr.s_addr = inet_addr(argv[1]);
	servAddr.sin_port = htons(atoi(argv[2]));

	if (connect(hSocket, (SOCKADDR*)&servAddr, sizeof(servAddr)) == SOCKET_ERROR)
		ErrorHandling("connect() error!");

	strlen = recv(hSocket, message, sizeof(message) - 1, 0);
	if (strlen == -1)
		ErrorHandling("read() error!");

	printf("Message from server:%s", message);
	closesocket(hSocket);
	WSACleanup();
	return 0;
}

void ErrorHandling(char * message) {
	fputs(message, stderr);
	fputc('\n', stderr);
	exit(1);
}

3.运行

运行时直接进入到可执行程序文件,使用命令行运行

C:\tcpip>tcp_win_server 9190
C:\tcpip>tcp_win_client 127.0.0.1 9190

二、Linux环境下实现TCP通信

1.服务端

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>
void error_handling(char *message);
int main(int argc,char *argv[])
{
	int serv sock;
	int clnt sock;
	struct sockaddr in serv addr;
	struct sockaddr in clnt addr;
	socklen t clnt addr size;
	char message[]="Hello World!";
	if(argc!=2)
	{
		printf("Usage :%s<port>\n",argv[0]);
		exit(1);
	}
	serv sock=Socket(PF INET,SOCK STREAM,0);
	if(serv sock ==-1)
		error_handling("socket() error");
	memset(&serv_addr,0,sizeof(serv addr));
	serv_addr.sin_family=AF INET;
	serv_addr.sin_addr.s addr=htonl(INADDR ANY);
	serv_addr.sin_port=htons(atoi(argv[1]));
	if(bind(serv_sock,(struct sockaddr*)&serv_addr, sizeof(serv_addr))==-1)
		error_handling("bind() error");
	if(listen(serv sock,5)==-1)
		error_handling("listen() error");
	clnt addr size=sizeof(clnt addr);
	cInt sock=accept(sery sock,(struct sockaddr*)&cInt addr,&cInt addr size);
	if(clnt sock==-1)
		error_handling("accept() error");
	write(clnt_sock,message,sizeof(message));
	close(clnt sock);
	close(serv sock);return 0;
}
void error handling(char *message)
{
	fputs(message, stderr);
	fputc('\n',stderr);
	exit(1);
}

2.客户端

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>
void error handling(char *message);
int main(int argc, char* argv[])
{
	int sock;
	struct sockaddr_in serv_addr;
	char message[30];
	int str_len;
	if(argc!-3)
	{
		printf("Usage :%s<IP><port>\n",argv[0]);
		exit(1);
	}
	sock=socket(PF INET,SOCK STREAM, 0);
	if(sock == -1)
		error_handling("socket() error")
	memset(&serv addr,0,sizeof(serv addr));
	serv addr.sin family=AF INET;
	serv addr.sin addr.s addr-inet addr(argv[1]);
	serv_addr.sin port=htons(atoi(argv[2]));
	if(connect(sock,(struct sockaddr*)&serv addr,sizeof(serv_addr))==-1)
		error_handling("connect() error!");
	str len=read(sock,message,sizeof(message)-1);
	if(str len=--1)
		error_handling("read()error!");
	printf("Message from server :Xs n",message);
	close(sock);
	return 0;
}
void error handling(char*message)
{
	fputs(message, stderr)fputc('\n',stderr);
	exit(1);
}

三、Qt实现TCP通信

相对于前边两种方法,QT进行了一定封装,使用起来更加简洁。
在这里插入图片描述

1.服务端

mainwindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include  <QtNetwork>
#if _MSC_VER >= 1600
#pragma execution_character_set("utf-8")
#endif

QString MainWindow::getLocalIP()
{
    //获取本机IPv4地址
    //! 本地主机名, QHostInfo 的静态函数 localHostName()可获取本机的主机名
    QString hostName = QHostInfo::localHostName();
    //! 返回指定的主机名的IP地址
    QHostInfo hostInfo = QHostInfo::fromName(hostName);
    QString localIP = "";
    //! 返回与 hostName()主机关联的IP地址列表
    QList<QHostAddress> addList = hostInfo.addresses();//

    for (int i = 0; i < addList.count(); i++)
    {
        QHostAddress aHost = addList.at(i);
        if (QAbstractSocket::IPv4Protocol == aHost.protocol())
        {
            //192.168.23.114
            localIP=aHost.toString();
            break;
        }
    }
    return localIP;
}

void MainWindow::closeEvent(QCloseEvent *event)
{//关闭窗口时停止监听
    if (tcpServer->isListening())
        tcpServer->close();;//停止网络监听
    event->accept();
}

MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    LabListen=new QLabel("监听状态:");
    LabListen->setMinimumWidth(150);
    ui->statusBar->addWidget(LabListen);

    LabSocketState=new QLabel("Socket状态:");//
    LabSocketState->setMinimumWidth(200);
    ui->statusBar->addWidget(LabSocketState);
    //本机IP
    QString localIP = getLocalIP();
    this->setWindowTitle(this->windowTitle()+"----本机IP:"+localIP);
    ui->comboIP->addItem(localIP);
    //! tcp服务端
    tcpServer = new QTcpServer(this);
    //! 如果有新的连接
    connect(tcpServer, SIGNAL(newConnection()), this, SLOT(onNewConnection()));
}

MainWindow::~MainWindow()
{
    delete ui;
}

//! 服务端有新的连接时
void MainWindow::onNewConnection()
{
//    ui->plainTextEdit->appendPlainText("有新连接");
    //! 创建socket,返回下一个等待接入的连接
    tcpSocket = tcpServer->nextPendingConnection();
    //! connectToHost()成功连接到服务器后发射此信号,连接成功后显示
    connect(tcpSocket, SIGNAL(connected()), this, SLOT(onClientConnected()));
    //! 客户端接入时
    onClientConnected();
    //! 当socket断开连接后发射此信号
    connect(tcpSocket, SIGNAL(disconnected()), this, SLOT(onClientDisconnected()));
    //! 当socket的状态变化时发射此信号,参数socketState表示了socket当前的状态
    connect(tcpSocket,SIGNAL(stateChanged(QAbstractSocket::SocketState)), this,
            SLOT(onSocketStateChange(QAbstractSocket::SocketState)));
    onSocketStateChange(tcpSocket->state());
    //! 当缓冲区有新数据需要读取时发射此信号,在此信号的槽函数里读取缓冲区的数据
    connect(tcpSocket, SIGNAL(readyRead()), this, SLOT(onSocketReadyRead()));
}

//socket状态变化时
void MainWindow::onSocketStateChange(QAbstractSocket::SocketState socketState)
{
    switch(socketState)
    {
    case QAbstractSocket::UnconnectedState:
        LabSocketState->setText("scoket状态:UnconnectedState");
        break;
    case QAbstractSocket::HostLookupState:
        LabSocketState->setText("scoket状态:HostLookupState");
        break;
    case QAbstractSocket::ConnectingState:
        LabSocketState->setText("scoket状态:ConnectingState");
        break;
    case QAbstractSocket::ConnectedState:
        LabSocketState->setText("scoket状态:ConnectedState");
        break;
    case QAbstractSocket::BoundState:
        LabSocketState->setText("scoket状态:BoundState");
        break;
    case QAbstractSocket::ClosingState:
        LabSocketState->setText("scoket状态:ClosingState");
        break;
    case QAbstractSocket::ListeningState:
        LabSocketState->setText("scoket状态:ListeningState");
    }
}

//客户端接入时
void MainWindow::onClientConnected()
{
    ui->plainTextEdit->appendPlainText("**client socket connected");
    ui->plainTextEdit->appendPlainText("**peer name:" + tcpSocket->peerName());
    //! 在已连接状态下,返回对方socket的地址
    ui->plainTextEdit->appendPlainText("**peer address:" + tcpSocket->peerAddress().toString());
    ui->plainTextEdit->appendPlainText("**peer port:" + QString::number(tcpSocket->peerPort()));
}

void MainWindow::onClientDisconnected()
{//客户端断开连接时
    ui->plainTextEdit->appendPlainText("**client socket disconnected");
    tcpSocket->deleteLater();
    //    deleteLater();//QObject::deleteLater();
}

void MainWindow::onSocketReadyRead()
{//读取缓冲区行文本
//    QStringList   lines;
    while(tcpSocket->canReadLine())
        ui->plainTextEdit->appendPlainText("[in] " + tcpSocket->readLine());
//        lines.append(clientConnection->readLine());
}

//开始监听
void MainWindow::on_actStart_triggered()
{
    //! IP地址
    QString IP = ui->comboIP->currentText();
    //! 端口
    quint16 port = ui->spinPort->value();
    QHostAddress addr(IP);
    tcpServer->listen(addr, port);//
//    tcpServer->listen(QHostAddress::LocalHost,port);// Equivalent to QHostAddress("127.0.0.1").
    ui->plainTextEdit->appendPlainText("**开始监听...");
    ui->plainTextEdit->appendPlainText("**服务器地址:" + tcpServer->serverAddress().toString());
    ui->plainTextEdit->appendPlainText("**服务器端口:" + QString::number(tcpServer->serverPort()));
    ui->actStart->setEnabled(false);
    ui->actStop->setEnabled(true);
    LabListen->setText("监听状态:正在监听");
}

void MainWindow::on_actStop_triggered()
{//停止监听
    if (tcpServer->isListening()) //tcpServer正在监听
    {
        tcpServer->close();//停止监听
        ui->actStart->setEnabled(true);
        ui->actStop->setEnabled(false);
        LabListen->setText("监听状态:已停止监听");
    }
}

void MainWindow::on_actClear_triggered()
{
    ui->plainTextEdit->clear();
}

void MainWindow::on_btnSend_clicked()
{//发送一行字符串,以换行符结束
    QString  msg=ui->editMsg->text();
    ui->plainTextEdit->appendPlainText("[out] "+msg);
    ui->editMsg->clear();
    ui->editMsg->setFocus();

    QByteArray  str=msg.toUtf8();
    str.append('\n');//添加一个换行符
    tcpSocket->write(str);
}

void MainWindow::on_actHostInfo_triggered()
{//获取本机地址
    QString hostName=QHostInfo::localHostName();//本地主机名
    ui->plainTextEdit->appendPlainText("本机主机名:"+hostName+"\n");
    QHostInfo   hostInfo=QHostInfo::fromName(hostName);

    QList<QHostAddress> addList=hostInfo.addresses();//
    if (!addList.isEmpty())
    for (int i=0;i<addList.count();i++)
    {
        QHostAddress aHost=addList.at(i);
        if (QAbstractSocket::IPv4Protocol==aHost.protocol())
        {
            QString IP=aHost.toString();
            ui->plainTextEdit->appendPlainText("本机IP地址:"+aHost.toString());
            if (ui->comboIP->findText(IP)<0)
                ui->comboIP->addItem(IP);
        }
    }

}

mainwindow.h

```cpp
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include    <QTcpServer>
#include    <QLabel>

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT
private:
    QLabel  *LabListen;//状态栏标签
    QLabel  *LabSocketState;//状态栏标签
    QTcpServer *tcpServer; //TCP服务器
    QTcpSocket *tcpSocket;//TCP通讯的Socket
    QString getLocalIP();//获取本机IP地址
protected:
    void   closeEvent(QCloseEvent *event);
public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();
private slots:
//自定义槽函数
    void    onNewConnection();//QTcpServer的newConnection()信号
    void    onSocketStateChange(QAbstractSocket::SocketState socketState);
    void    onClientConnected(); //Client Socket connected
    void    onClientDisconnected();//Client Socket disconnected
    void    onSocketReadyRead();//读取socket传入的数据
//UI生成的
    void on_actStart_triggered();
    void on_actStop_triggered();
    void on_actClear_triggered();
    void on_btnSend_clicked();
    void on_actHostInfo_triggered();
private:
    Ui::MainWindow *ui;
};

#endif // MAINWINDOW_H

1.客户端

mainwindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include  <QHostAddress>
#include  <QHostInfo>
#if _MSC_VER >= 1600
#pragma execution_character_set("utf-8")
#endif
QString MainWindow::getLocalIP()
{
    QString hostName = QHostInfo::localHostName();//本地主机名
    QHostInfo hostInfo = QHostInfo::fromName(hostName);
    QString localIP = "";
    QList<QHostAddress> addList = hostInfo.addresses();//
    for (int i = 0; i < addList.count(); i++)
    {
        QHostAddress aHost = addList.at(i);
        if (QAbstractSocket::IPv4Protocol == aHost.protocol())
        {
            localIP=aHost.toString();
            break;
        }
    }
    return localIP;
}
void MainWindow::closeEvent(QCloseEvent *event)
{
    if (tcpClient->state()==QAbstractSocket::ConnectedState)
        tcpClient->disconnectFromHost();
    event->accept();
}

MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    tcpClient = new QTcpSocket(this); //创建socket变量
    LabSocketState=new QLabel("Socket状态:");//状态栏标签
    LabSocketState->setMinimumWidth(250);
    ui->statusBar->addWidget(LabSocketState);
    //本机IP
    QString localIP = getLocalIP();
    this->setWindowTitle(this->windowTitle() + "----本机IP:" + localIP);
    ui->comboServer->addItem(localIP);

    connect(tcpClient,SIGNAL(connected()),this,SLOT(onConnected()));
    connect(tcpClient,SIGNAL(disconnected()),this,SLOT(onDisconnected()));
    connect(tcpClient,SIGNAL(stateChanged(QAbstractSocket::SocketState)),this,
            SLOT(onSocketStateChange(QAbstractSocket::SocketState)));
    connect(tcpClient,SIGNAL(readyRead()),this,SLOT(onSocketReadyRead()));
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::onConnected()
{ //connected()信号槽函数
    ui->plainTextEdit->appendPlainText("**已连接到服务器");
    ui->plainTextEdit->appendPlainText("**peer address:" + tcpClient->peerAddress().toString());
    ui->plainTextEdit->appendPlainText("**peer port:" + QString::number(tcpClient->peerPort()));
    ui->actConnect->setEnabled(false);
    ui->actDisconnect->setEnabled(true);
}

void MainWindow::onDisconnected()
{//disConnected()信号槽函数
    ui->plainTextEdit->appendPlainText("**已断开与服务器的连接");
    ui->actConnect->setEnabled(true);
    ui->actDisconnect->setEnabled(false);
}

void MainWindow::onSocketReadyRead()
{//readyRead()信号槽函数
    while(tcpClient->canReadLine())
        ui->plainTextEdit->appendPlainText("[in] "+tcpClient->readLine());
}

void MainWindow::onSocketStateChange(QAbstractSocket::SocketState socketState)
{//stateChange()信号槽函数
    switch(socketState)
    {
    case QAbstractSocket::UnconnectedState:
        LabSocketState->setText("scoket状态:UnconnectedState");
        break;
    case QAbstractSocket::HostLookupState:
        LabSocketState->setText("scoket状态:HostLookupState");
        break;
    case QAbstractSocket::ConnectingState:
        LabSocketState->setText("scoket状态:ConnectingState");
        break;
    case QAbstractSocket::ConnectedState:
        LabSocketState->setText("scoket状态:ConnectedState");
        break;
    case QAbstractSocket::BoundState:
        LabSocketState->setText("scoket状态:BoundState");
        break;
    case QAbstractSocket::ClosingState:
        LabSocketState->setText("scoket状态:ClosingState");
        break;
    case QAbstractSocket::ListeningState:
        LabSocketState->setText("scoket状态:ListeningState");
    }
}

void MainWindow::on_actConnect_triggered()
{//连接到服务器
    QString     addr=ui->comboServer->currentText();
    quint16     port=ui->spinPort->value();
    tcpClient->connectToHost(addr,port);
//    tcpClient->connectToHost(QHostAddress::LocalHost,port);
}

void MainWindow::on_actDisconnect_triggered()
{//断开与服务器的连接
    if (tcpClient->state()==QAbstractSocket::ConnectedState)
        tcpClient->disconnectFromHost();
}

void MainWindow::on_actClear_triggered()
{
    ui->plainTextEdit->clear();
}

void MainWindow::on_btnSend_clicked()
{//发送数据
    QString  msg=ui->editMsg->text();
    ui->plainTextEdit->appendPlainText("[out] "+msg);
    ui->editMsg->clear();
    ui->editMsg->setFocus();
    QByteArray str = msg.toUtf8();
    str.append('\n');
    tcpClient->write(str);
}

mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include    <QTcpSocket>
#include    <QLabel>

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT
private:
    QTcpSocket  *tcpClient;  //socket
    QLabel  *LabSocketState;  //状态栏显示标签

    QString getLocalIP();//获取本机IP地址
protected:
    void    closeEvent(QCloseEvent *event);
public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();

private slots:
//自定义槽函数
    void    onConnected();
    void    onDisconnected();
    void    onSocketStateChange(QAbstractSocket::SocketState socketState);
    void    onSocketReadyRead();//读取socket传入的数据
//
    void on_actConnect_triggered();

    void on_actDisconnect_triggered();

    void on_actClear_triggered();

    void on_btnSend_clicked();

private:
    Ui::MainWindow *ui;
};

#endif // MAINWINDOW_H

总结

以上就是今天要讲的内容,本文整理了三种实现TCP通信的方法,从上层到偏底层,对于新手理解通信原理有极大帮助。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

RAG文本解析工具open-parse

简介 对于RAG来说&#xff0c;将文本有效的分块(chucking)是很重要的一件事&#xff0c;open-parse是一个用来分块pdf的开源工具&#xff0c;它主要基于视觉驱动(Visually-Driven)的方式来将文档分块&#xff0c;也就是说它不仅仅是按照段落或者字数来对文档分块&#xff0c;而…

easyx 按键信息

前言 看看代码吧 ExMessage msg { 0 }; bool button(int x, int y, int w, int h, const char* text) {//绘制按钮setfillcolor(RGB(230, 231, 232));fillroundrect(x, y, x w, y h, 5, 5);if ((msg.x > x && msg.x<x w && msg.y>y && …

为什么要分库分表?(设计高并发系统的时候,数据库层面该如何设计?)

目录 1.分表 2.分库 说白了&#xff0c;分库分表是两回事儿&#xff0c;大家可别搞混了&#xff0c;可能是光分库不分表&#xff0c;也可能是光分表不分库&#xff0c;都有可能。 我先给大家抛出来一个场景。 假如我们现在是一个小创业公司(或者是一个 BAT …

java反序列化之URLDNS链学习

一、前言 近来学习java反序列化&#xff0c;听p神所说这个URLDNS利用链比较好理解&#xff0c;故决定由此进入学习的第一篇。 URLDNS是Java反序列化中比较简单的一个链&#xff0c;由于URLDNS不需要依赖第三方的包&#xff0c;同时不限制jdk的版本&#xff0c;所以通常用于检…

hertzbeat 源码阅读记录

关于自定义标签的说明 EmailValid.java HostValid PhoneNumValid 枚举值说明&#xff1a;

【OpenGL实践08】现代渲染管线在GLUT和Pygame和Qt.QOpenGLWidget上各自的实现代码

Qt.QOpenGLWidget进行现代渲染管线实验效果 一、说明 据说QOpenGLWidget是用来取代QGLWidget的继承者&#xff0c;我们试图将GLUT上的旧代码改成QOpenGLWidget&#xff0c;本以为差别不大&#xff0c;轻易搞定&#xff0c;经实践发现要付出极大努力才能完成。经多次实验发现G…

Java面试八股之Java中为什么没有全局变量

Java中为什么没有全局变量 Java中没有传统意义上的全局变量&#xff0c;这是因为Java语言设计遵循面向对象的原则&#xff0c;强调封装性和模块化&#xff0c;以及避免全局状态带来的副作用。 封装性&#xff1a; 全局变量违反了面向对象编程中的封装原则&#xff0c;即隐藏对…

【ZYNQ】zynq启动模式及程序固化

一、前言 由于zynq含有arm cpu ,其启动模式由ps主导&#xff0c;与纯逻辑的fpga不相同&#xff0c;此处做一个记录。 二、zynq启动模式 关于zynq的启动模式详细内容可以参考官方文档&#xff1a;ug585-Zynq 7000 SoC Technical Reference Manual&#xff0c;第六章。 2.1 启…

帮助中心系统搭建不再是难题,这几个工具来帮你

在面临客户服务挑战时&#xff0c;有效的帮助中心系统是提升用户满意度和解决问题效率的关键。幸运的是&#xff0c;搭建一个功能全面的帮助中心不再是什么难事。下面&#xff0c;我要为你介绍三款能够帮忙打造帮助中心的超实用工具&#xff0c;让你的客户支持体验迅速升级。 1…

网页使用之如何返回json/xml

后端返回json数据给前端进行渲染的方式比较熟悉&#xff0c;至于返回html页面&#xff0c;返回xml的方式接触逐渐减少&#xff0c;来在项目中熟悉这一点。 返回文本数据 json姿势的返回实属最简单的方式&#xff0c;在SpringBoot应用中&#xff0c;有两种简单的方式 1.直接在…

S32K的JLINK与PE接线方法与刷程序失败问题

S32K的JLINK与PE接线方法与刷程序失败问题 1、PE的接线方法2、JLINK的接线方法3、刷程序失败问题 1、PE的接线方法 2、JLINK的接线方法 3、刷程序失败问题 出现如下问题&#xff1a; Secure Debug might be enabled on this device.lf so.please unlock the device via PEmic…

一段音频驱动照片唱歌,EMO模型上线通义APP

把一段音频、一张照片输入AI模型&#xff0c;就能让图中人物开口唱歌说话&#xff0c;让奥黛丽赫本唱《上春山》、陶俑仕女说英文RAP、爱因斯坦说中文段子。不久前&#xff0c;这款名为EMO的模型因为阿里通义实验室的一篇论文火遍海内外&#xff0c;模型的产品化进程也广受关注…

运动耳机哪个牌子性价比高?推荐五款高性价比运动耳机

跑步、健身、游泳……无论你的运动喜好是什么&#xff0c;一款好的运动蓝牙耳机都能为你的运动体验加分。然而&#xff0c;市面上的运动蓝牙耳机品牌众多&#xff0c;如何选择一款既舒适又实用的产品呢&#xff1f;本文将为你提供一些选购运动蓝牙耳机建议&#xff0c;并为你推…

企业规模扩大,SD-WAN实现跨省快速组网

随着数字化时代的飞速发展&#xff0c;企业面临着前所未有的挑战与机遇。5G、VoIP、AI和物联网等新技术的兴起&#xff0c;不仅改变了商业格局&#xff0c;也对企业网络提出了更高的要求。随着企业规模的不断扩大&#xff0c;企业如何搭建跨省的、高性能、超融合、简化运维的组…

解决Jmeter 4.x 请求到elasticsearch 中文乱码的问题

文章目录 前言解决Jmeter 4.x 请求到elasticsearch 中文乱码的问题 前言 如果您觉得有用的话&#xff0c;记得给博主点个赞&#xff0c;评论&#xff0c;收藏一键三连啊&#xff0c;写作不易啊^ _ ^。   而且听说点赞的人每天的运气都不会太差&#xff0c;实在白嫖的话&#…

MOS产品在光伏逆变器上的应用与数据分析

2023年全球光伏装机量表现优异&#xff0c;根据BloombergNEF统计数据&#xff0c;2023年全球光伏新增装机量444GW&#xff0c;同比增长76.2%&#xff0c;其中约一半新增装机量来自中国。 中国光伏新技术迭代不断&#xff0c;产业链降本增效加速。根据CPIA数据&#xff0c;2022年…

Linux网络-DNS域名解析服务

目录 一.DNS相关介绍 1.DNS是什么 2.DNS系统的分布式数据结构 根域 顶级域 二级域 子域 主机 3.服务器类型 主域名服务器 从域名服务器 缓存域名服务器 转发域名服务器 二.DNS域名解析 1.DNS域名解析方式及功能 2.DNS域名解析查询方式 2.1.递归查询&#xff0…

【LLM多模态】Qwen-VL模型结构和训练流程

note 观点&#xff1a;现有很多多模态大模型是基于预训练&#xff08;和SFT对齐&#xff09;的语言模型&#xff0c;将视觉特征token化并对齐到语言空间中&#xff0c;利用语言模型得到多模态LLM的输出。如何设计更好的图像tokenizer以及定位语言模型在多模态LLM中的作用很重要…

零基础HTML教程(27)--表单元素属性

文章目录 1. 背景2. disabled:禁用3. readonly:直读4. checked:选中5. maxlength:最大输入字符数6. 小结 1. 背景 上一篇我们讲了表单元素的两个属性id和name&#xff0c;其实表单元素还有其他几个常用属性&#xff0c;我们逐一介绍。 2. disabled:禁用 disabled属性表示禁用…

大厂面试题:从源码的角度分析MyBatis中#{}与${}的区别

大家好&#xff0c;我是王有志。 今天我会通过源码来分析一道京东&#xff0c;联储证券和爱奇艺都考察过的 MyBatis 面试题&#xff1a;MyBatis 中“#{}”和“${}”有什么区别&#xff1f;是否可以使用“#{}”来传递 order by 的动态列&#xff1f; “#{}”和“${}”有什么区…
最新文章