qt配合映美精取图开发

  1. 最近开发一个项目,用映美精相机配合halcon做取图开发,由于网上资料小特意写个记录。
  2. 到映美精官网下载驱动,映美精官网,下载映美精的工具开发包SDK 映美精的SDK
  3. 下载SDK后找到classlib文件夹
    请添加图片描述
    里面就是SDK
  4. 新建一个qt程序,引入SDK
    请添加图片描述
  5. 新建一个相机类

头文件

#ifndef CAMERAGRAP_H
#define CAMERAGRAP_H#include <QObject>
#include "QDebug"
#include <tisudshl.h>
#include <algorithm>/***sink监控***/
class SinkListener : public DShowLib::FrameQueueSinkListener
{
public:/***槽链接成功***/void    sinkConnected(DShowLib::FrameQueueSink& sink,const DShowLib::FrameTypeInfo& frameType );/***取到图片是响应***/void framesQueued( DShowLib::FrameQueueSink& sink );/***槽链接断开回调***/void sinkDisconnected(DShowLib::FrameQueueSink& sink );
};class CameraGrap : public QObject
{Q_OBJECT
public:explicit CameraGrap(QObject *parent = nullptr);~CameraGrap();/***初始化***/void Init();/***读取配置***/void ReadConfig();/***保存配置***/bool WriteConfig();/***开始相机***/void StartCamera();/***停止相机***/void StopCamera();/***释放资源***/void ReleaseSource();/***设置相机的触发模式为触发取图***/void SetCameraTriggerTakeImage();/***设置相机试试视频取图***/void SetCameraLiveTakeImage();/***设置相机曝光***/void SetCameraExpource(double expource_);/***设置相机增益***/void SetCameraGain(double gain_);/***触发下相机取图***/void TriggerCameraTakeImage();// /***槽链接成功***/// void    sinkConnected(DShowLib::FrameQueueSink& sink,//                    const DShowLib::FrameTypeInfo& frameType );// /***取到图片是响应***/// void framesQueued( DShowLib::FrameQueueSink& sink );// /***槽链接断开回调***/// void sinkDisconnected(DShowLib::FrameQueueSink& sink );// /***重写取图回调函数***/// void frameReady(DShowLib::Grabber& caller, smart_ptr<DShowLib::MemBuffer> pBuffer, DWORD FrameNumber ) override;// void overlayCallback(DShowLib::Grabber& caller, smart_ptr<DShowLib::OverlayBitmap> pBitmap, const DShowLib::tsMediaSampleDesc& desc );signals:// /***获取图片完成标志***/// void FinallyGetImage();
public:static CameraGrap _camer_grap;/***相机名称***/QString _camera_name;/***相机视频的格式***/QString _camera_video_format;/***相机曝光***/double _camera_expource;/***相机增益***/double _camera_gain;/***相机抗干扰数***/double _camera_noise_suppression;/***相机有无标志***/bool _camera_exist;/***创建一个抓拍,一定创建成指针形式,不然会跟***/DShowLib::Grabber* _grabber;// /***sink监控***/SinkListener _listener_instance;// DShowLib::FrameTypeInfoArray _accepted_types;/***接受图片的格式***/DShowLib::FrameTypeInfo _accepted_type;/***槽***/DShowLib::tFrameQueueSinkPtr _psink;
};#endif // CAMERAGRAP_H

内容文件

#include "cameragrap.h"
#include <DeeplearnInspection/deeplearninspection.h>
#include <QCoreApplication>
#include "xlsxdocument.h"
#include "QMetaMethod"
// #include "ic4-interop/interop-HALCON.h"CameraGrap CameraGrap::_camer_grap;void SinkListener::sinkConnected(DShowLib::FrameQueueSink& sink,const DShowLib::FrameTypeInfo& frameType )
{UNREFERENCED_PARAMETER( frameType );/***链接成功分配内存***/sink.allocAndQueueBuffers(1);
}void SinkListener::framesQueued(DShowLib::FrameQueueSink& sink)
{DShowLib::tFrameQueueBufferPtr buffer = sink.popOutputQueueBuffer();//unsigned int frame_number = buffer->getFrameMetaData().mediaSampleDesc.FrameNumber;// DShowLib::tColorformatEnum format_= buffer->getFrameType().getColorformat();int width_=buffer->getFrameType().dim.cx;int height_=buffer->getFrameType().dim.cy;// HalconCpp::GenImageInterleaved(&ho_Image, (void*)pBuffer, "rgb", width, height, 0, "byte", width * 3, height, 0, 0);HalconCpp::HTuple hptr_=(Hlong)buffer->getPtr();HalconCpp::GenImage1(&DeeplearnInspection::_deeplearn_inspection._image,"byte",width_,height_,hptr_);DeeplearnInspection::_deeplearn_inspection._image_exist=true;hptr_.Clear();/***释放内存资源***/buffer.destroy();int size_input_= sink.getInputQueueSize();int size_output_=sink.getOutputQueueSize();sink.popAllOutputQueueBuffers().clear();sink.popAllInputQueueBuffers().clear();/***重新分配内存资源***/sink.allocAndQueueBuffers(1);size_input_= sink.getInputQueueSize();size_output_=sink.getOutputQueueSize();/***触发相机取图完成***/DeeplearnInspection::_deeplearn_inspection.TriggerCameraImageWriteFinally();
}void SinkListener::sinkDisconnected(DShowLib::FrameQueueSink& sink)
{;
}CameraGrap::CameraGrap(QObject *parent): QObject{parent}
{
}CameraGrap::~CameraGrap()
{
}void CameraGrap::Init()
{/***读取配置***/ReadConfig();/***初始化相机底层***/DShowLib::InitLibrary();/***创建一个抓拍***/_grabber=new DShowLib::Grabber();/***获取相机驱动***/auto cameras_= _grabber->getAvailableVideoCaptureDevices();/***判断有没有相机***/int camera_count_= cameras_->size();if(camera_count_>0){for(int i=0;i<camera_count_;i++){/***获取相机名称***/std::string camera_name_;camera_name_=cameras_->at(i).getName();if(camera_name_==_camera_name.toStdString()){i=camera_count_;if(_grabber->openDev(camera_name_)){//_grabber->showVCDPropertyPage();/***设置图片格式***/// _grabber->setVideoFormat("Y800 (1424x712)");DShowLib::dstringa video_format_=_camera_video_format.toStdString();_grabber->setVideoFormat(video_format_);/***设置外部出发***/_grabber->setExternalTrigger(1);/***给如抗误触发参数***/DShowLib::tIVCDAbsoluteValuePropertyPtr noise_suppression_time_ = _grabber->getVCDPropertyInterface<DShowLib::IVCDAbsoluteValueProperty>(DShowLib::VCDID_Trigger, DShowLib::VCDElement_TriggerNoiseSuppressionTime);if(noise_suppression_time_==NULL){qDebug() << "noise suppression time auto is failed";}else{long max_=noise_suppression_time_->getRangeMax();long min_=noise_suppression_time_->getRangeMin();long cvalue_;cvalue_=noise_suppression_time_->getValue();qDebug() << "noise suppression time is "+QString::number(cvalue_);if((max_>=_camera_noise_suppression)&&(min_<=_camera_noise_suppression)){noise_suppression_time_->setValue(_camera_noise_suppression);}else{noise_suppression_time_->setValue(min_);}}/***设置帧率***/_grabber->setFPS(120);// Enable the overlay bitmap to display the frame counter in the live video._grabber->setOverlayBitmapPathPosition( DShowLib::ePP_DEVICE );_grabber->getOverlay(DShowLib::ePP_DEVICE )->setEnable( true );// Create a FrameTypeInfoArray data structure describing the allowed color formats.//_accepted_types= DShowLib::FrameTypeInfoArray::createStandardTypesArray();/***设置槽接受图片的格式***/_accepted_type =DShowLib::eY800;// Create the frame sink_psink= DShowLib::FrameQueueSink::create(this->_listener_instance, _accepted_type);// Apply the sink to the grabber._grabber->setSinkType(_psink);/***设置曝光手动***/DShowLib::tIVCDSwitchPropertyPtr exposure_auto = _grabber->getVCDPropertyInterface<DShowLib::IVCDSwitchProperty>( DShowLib::VCDID_Exposure, DShowLib::VCDElement_Auto);if( exposure_auto == NULL ){qDebug() << "exposure auto is failed";}else{exposure_auto->setSwitch(false);}/***获取曝光的范围,设置相机曝光***/DShowLib::tIVCDRangePropertyPtr exposure_range = _grabber->getVCDPropertyInterface<DShowLib::IVCDRangeProperty>(DShowLib::VCDID_Exposure, DShowLib::VCDElement_Value);if( exposure_range == NULL ){qDebug() << "exposure auto is failed";}else{// std::cout << "Current Exposure range value: " << exposure_range->getValue() << std::endl;// std::cout << "Exposure range range: [" << exposure_range->getRangeMin() << ".." << exposure_range->getRangeMax() << "]" << std::endl;long max_=exposure_range->getRangeMax();long min_=exposure_range->getRangeMin();long cvalue_;cvalue_=exposure_range->getValue();qDebug() << "expource is "+QString::number(cvalue_);if((max_>=_camera_expource)&&(min_<=_camera_expource)){exposure_range->setValue(_camera_expource);}else{exposure_range->setValue(min_);}}// /***确认曝光是否设置成功***/// DShowLib::tIVCDAbsoluteValuePropertyPtr exposure_absolute = _grabber.getVCDPropertyInterface<DShowLib::IVCDAbsoluteValueProperty>( DShowLib::VCDID_Exposure,DShowLib::VCDElement_Value);// if( exposure_absolute == NULL )// {//     qDebug() << "vilation is failed";// }// else// {//     long exposure_= exposure_absolute->getValue();//     qDebug() << "expource is "+QString::number(exposure_);// }/***设置增益手动***/DShowLib::tIVCDSwitchPropertyPtr gain_auto = _grabber->getVCDPropertyInterface<DShowLib::IVCDSwitchProperty>( DShowLib::VCDID_Gain, DShowLib::VCDElement_Auto);if( gain_auto == NULL ){qDebug() << "exposure auto is failed";}else{gain_auto->setSwitch(false);}/***获取增益范围,设置增益***/DShowLib::tIVCDRangePropertyPtr gain_range = _grabber->getVCDPropertyInterface<DShowLib::IVCDRangeProperty>(DShowLib::VCDID_Gain, DShowLib::VCDElement_Value);if( gain_range == NULL ){qDebug() << "exposure auto is failed";}else{long max_=gain_range->getRangeMax();long min_=gain_range->getRangeMin();long cvalue_;cvalue_=gain_range->getValue();if((max_>=_camera_gain)&&(min_<=_camera_gain)){gain_range->setValue(_camera_gain);}else{gain_range->setValue(min_);}}// /***确认曝光是否设置成功***/// DShowLib::tIVCDAbsoluteValuePropertyPtr gain_absolute = _grabber.getVCDPropertyInterface<DShowLib::IVCDAbsoluteValueProperty>( DShowLib::VCDID_Gain,DShowLib::VCDElement_Value);// if( gain_absolute == NULL )// {//     qDebug() << "vilation is failed";// }// else// {//     long gain_= gain_absolute->getValue();//     qDebug() << "gain is "+QString::number(gain_);// }_camera_exist=true;}}}}else{_camera_exist=false;qDebug() << "no found devices";}
}void CameraGrap::ReadConfig()
{QString config_path_=QCoreApplication::applicationDirPath()+"/CameraConfig.xlsx";QFile file_(config_path_);if(file_.exists()){QXlsx::Document xlsx_(config_path_);if(xlsx_.load()){int row_count_=xlsx_.dimension().rowCount();int column_count_=xlsx_.dimension().columnCount();if((row_count_>4)&&(column_count_>1)){_camera_name= xlsx_.cellAt(2,2)->value().toString();_camera_expource=xlsx_.cellAt(3,2)->value().toDouble();_camera_gain=xlsx_.cellAt(4,2)->value().toDouble();_camera_video_format=xlsx_.cellAt(5,2)->value().toString();_camera_noise_suppression=xlsx_.cellAt(6,2)->value().toDouble();}else{qDebug() << "Failed to load CameraConfig.xlsx file.";}}}else{qDebug() << "CameraConfig.xlsx file is not exist";}file_.close();
}bool CameraGrap::WriteConfig()
{bool ok_=false;QString config_path_=QCoreApplication::applicationDirPath()+"/CameraConfig.xlsx";QXlsx::Document xlsx_;/***写入抬头***/xlsx_.write(1,1,"名称");xlsx_.write(1,2,"值");xlsx_.write(2,1,"CameraName");xlsx_.write(2,2,_camera_name);xlsx_.write(3,1,"Expource");xlsx_.write(3,2,QString::number(_camera_expource));xlsx_.write(4,1,"Gain");xlsx_.write(4,2,QString::number(_camera_gain));xlsx_.write(5,1,"VideoFormat");xlsx_.write(5,2,_camera_video_format);xlsx_.write(6,1,"NoiseSuppression");xlsx_.write(6,2,_camera_noise_suppression);if(!xlsx_.saveAs(config_path_)){qDebug() << "save the DataCache.xlsx failed";}else{ok_=true;}return ok_;
}void CameraGrap::StartCamera()
{if(_camera_exist==true){_grabber->startLive(false);}
}void CameraGrap::StopCamera()
{if(_camera_exist==true){_grabber->stopLive();}
}void CameraGrap::ReleaseSource()
{if(_camera_exist==true){if (_grabber->isDevOpen()){if(_grabber->isLive()){_grabber->stopLive();}_grabber->closeDev();}}delete _grabber;
}void CameraGrap::SetCameraTriggerTakeImage()
{if(_camera_exist==true){/***设置触发模式为软触发***/_grabber->setExternalTrigger(true);}
}void CameraGrap::SetCameraLiveTakeImage()
{if(_camera_exist==true){/***设置相机直播模式***/_grabber->setExternalTrigger(false);}
}void CameraGrap::SetCameraExpource(double expource_)
{if(_camera_exist==true){_camera_expource =expource_;/***获取曝光的范围,设置相机曝光***/DShowLib::tIVCDRangePropertyPtr exposure_range = _grabber->getVCDPropertyInterface<DShowLib::IVCDRangeProperty>(DShowLib::VCDID_Exposure, DShowLib::VCDElement_Value);if( exposure_range == NULL ){qDebug() << "exposure auto is failed";}else{// std::cout << "Current Exposure range value: " << exposure_range->getValue() << std::endl;// std::cout << "Exposure range range: [" << exposure_range->getRangeMin() << ".." << exposure_range->getRangeMax() << "]" << std::endl;long max_=exposure_range->getRangeMax();long min_=exposure_range->getRangeMin();long cvalue_;cvalue_=exposure_range->getValue();qDebug() << "expource is "+QString::number(cvalue_);if((max_>_camera_expource)&&(min_<_camera_expource)){exposure_range->setValue(_camera_expource);}else{exposure_range->setValue(min_);}}}
}void CameraGrap::SetCameraGain(double gain_)
{if(_camera_exist==true){_camera_gain=gain_;DShowLib::tIVCDRangePropertyPtr gain_range = _grabber->getVCDPropertyInterface<DShowLib::IVCDRangeProperty>(DShowLib::VCDID_Gain, DShowLib::VCDElement_Value);if( gain_range == NULL ){qDebug() << "exposure auto is failed";}else{long max_=gain_range->getRangeMax();long min_=gain_range->getRangeMin();long cvalue_;cvalue_=gain_range->getValue();if((max_>_camera_gain)&&(min_<_camera_gain)){gain_range->setValue(_camera_gain);}else{gain_range->setValue(min_);}}}
}void CameraGrap::TriggerCameraTakeImage()
{if(_camera_exist==true){DShowLib::tIVCDButtonPropertyPtr btn_= _grabber->getVCDPropertyInterface<DShowLib::IVCDButtonProperty>(DShowLib::VCDID_TriggerMode, DShowLib::VCDElement_SoftwareTrigger);if(btn_==NULL){}else{btn_->push();}}
}// void CameraGrap::frameReady(DShowLib::Grabber& caller,smart_ptr<DShowLib::MemBuffer> pBuffer,DWORD FrameNumber)
// {
//     // int width_=pBuffer->getFrameType().dim.cx;
//     // int height_=pBuffer->getFrameType().dim.cy;//     // uchar* ptr_=static_cast<uchar*>(pBuffer->getPtr());
//     // HalconCpp::HTuple hptr_=(int)ptr_;//     // HalconCpp::GenImage1(&DeeplearnInspection::_deeplearn_inspection._image,
//     //                      "byte",
//     //                      width_,
//     //                      height_,
//     //                      hptr_);
//     // hptr_.Clear();//     // QMetaMethod value_change_signal_=QMetaMethod::fromSignal(&CameraGrap::FinallyGetImage);
//     // if(this->isSignalConnected(value_change_signal_))
//     // {
//     //     emit FinallyGetImage();
//     // }
//     ;
// }// void CameraGrap::overlayCallback(DShowLib::Grabber& caller,
//                                  smart_ptr<DShowLib::OverlayBitmap> pBitmap,
//                                  const DShowLib::tsMediaSampleDesc& desc)
// {// }

6.代码分析
要获取相机的图片,主要创建一个类继承public DShowLib::FrameQueueSinkListener,
然后设置sink,代码如下:
// Create the frame sink
_psink= DShowLib::FrameQueueSink::create(this->_listener_instance, _accepted_type);
// Apply the sink to the grabber.
_grabber->setSinkType(_psink);
在相机取到图片后会回调sink,即回调framesQueued函数,在里面进行转换。

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

华为云计算HCIE-Cloud Computing V3.0试验考试北京考场经验分享

北京试验考场 北京考场位置 1.试验考场地址 北京市海淀区北清路156号中关村环保科技示范园区M地块Q21楼 考试场选择北京&#xff0c;就是上面这个地址&#xff0c;在预约考试的时候会显示地址&#xff0c;另外在临近考试的时候也会给你发邮件&#xff0c;邮件内会提示你考试…

LeetCode 509.斐波那契数

动态规划思想 五步骤&#xff1a; 1.确定dp[i]含义 2.递推公式 3.初始化 4.遍历顺序 5.打印dp数组 利用状态压缩&#xff0c;简化空间复杂度。在原代码中&#xff0c;dp 数组保存了所有状态&#xff0c;但实际上斐波那契数列的计算只需要前两个状态。因此&#xff0c;我们…

反向代理开发

1 概念 1.1 反向代理概念 反向代理是指以代理服务器来接收客户端的请求&#xff0c;然后将请求转发给内部网络上的服务器&#xff0c;将从服务器上得到的结果返回给客户端&#xff0c;此时代理服务器对外表现为一个反向代理服务器。 对于客户端来说&#xff0c;反向代理就相当于…

RabbitMQ — 异步调用

RabbitMQ 是一个开源的消息代理中间件&#xff0c;它使用高级消息队列协议&#xff08;AMQP, Advanced Message Queuing Protocol&#xff09;来实现不同系统之间的消息传递。它以 Erlang 语言编写&#xff0c;具有高可靠性、灵活性和易于扩展的特点&#xff0c;被广泛应用于异…

2025 年使用 Python 和 Go 解决 Cloudflare 问题

作为一名从事网络自动化和爬取工作的开发者&#xff0c;我亲眼目睹了日益复杂的安全性措施带来的挑战。其中一项挑战是 Cloudflare 的 Turnstile CAPTCHA 系统&#xff0c;目前该系统已在全球 2600 多万个网站上使用。这种先进的解决方案重新定义了我们对机器人检测的处理方式&…

大数据的实时处理:工具和最佳实践

在当今的数字世界中&#xff0c;数据以前所未有的速度从无数来源生成&#xff0c;包括社交媒体、物联网设备、电子商务平台等。随着组织认识到这些数据的潜在价值&#xff0c;他们越来越多地转向实时处理&#xff0c;以获得即时、可操作的见解。但是&#xff0c;实时处理大数据…

104、Python并发编程:基于事件Event实现多线程间的同步

引言 继续介绍关于多线程同步的实现方式&#xff0c;本文将介绍基于Event的线程同步方式。 本文的主要内容有&#xff1a; 1、什么是Event 2、Event的使用场景 3、Event的代码实例 4、Event与Condition的比较 什么是Event 在Python的多线程编程中&#xff0c;Event是一个…

第2章2.3立项【硬件产品立项的核心内容】

硬件产品立项的核心内容 2.3 硬件产品立项的核心内容2.3.1 第一步&#xff1a;市场趋势判断2.3.2 第二步&#xff1a;竞争对手分析1.竞争对手识别2.根据竞争对手分析制定策略 2.3.3 第三步&#xff1a;客户分析2.3.4 第四步&#xff1a;产品定义2.3.5 第五步&#xff1a;开发执…

ReactPress数据库表结构设计全面分析

ReactPress Github项目地址&#xff1a;https://github.com/fecommunity/reactpress 欢迎Star。 ReactPress是一个基于React框架开发的开源发布平台和内容管理系统&#xff08;CMS&#xff09;。它不仅支持用户在支持React和MySQL数据库的服务器上搭建自己的博客和网站&#…

ANDROIDWORLD: A Dynamic BenchmarkingEnvironment for Autonomous Agents论文学习

这个任务是基于androidenv的。这个环境之前学过&#xff0c;是一个用来进行强化学习的线上环境。而这篇文章的工作就是要给一些任务加上中间的奖励信号。这种训练环境的优点就是动态&#xff0c;与静态的数据集&#xff08;比如说我自己的工作&#xff09;不同&#xff0c;因此…

华为ENSP--ISIS路由协议

项目背景 为了确保资源共享、办公自动化和节省人力成本&#xff0c;公司E申请两条专线将深圳总部和广州、北京两家分公司网络连接起来。公司原来运行OSFP路由协议&#xff0c;现打算迁移到IS-IS路由协议&#xff0c;张同学正在该公司实习&#xff0c;为了提高实际工作的准确性和…

python-26-Python ORM系列之pymysql实现对数据库的增删改查及新建表

python-26-Python ORM系列之pymysql实现对数据库的增删改查及新建表 一.简介 在Python基础系列ORM部分我们为大家介绍了如何搭建MySQL数据和MySQL一些访问配置&#xff0c;同时细节的同学应该已经了解到了ORM的2个库pymysql和sqlalchemy&#xff1b; PyMySQL — MySQL 数据库…

ADSP21489 M25P16启动后无法使用USBi的问题

项目背景是ADSP21489 使用SPI MASTER 启动模式,程序存储在M25P16中 编译cces产生运行代码 第二步,插上USBi仿真器下载sigma topo 发现无法正常下载 操作多次发现需要目标板重新上点后需要拔插usbi才能下载和启动dsp程序 原因分析: 就是第一次插上usbi后,在给目标板上电,可…

量子计算包kaiwu安装过程踩过的坑

目录 1 安装过程 2 官方代码测试 3 踩坑说明 首先&#xff0c;目前的kaiwu版本仅支持python3.8&#xff0c;所以必须要下载python3.8才能运行kaiwu 1 安装过程 step1: 在页面的SDK标签下&#xff0c;找到对应操作系统的kaiwu包。 step2: 下载python3.8到本地&#xff0c;可…

线程相关概念

线程概念 线程是操作系统中一种基本的执行单元&#xff0c;是程序的最小调度单位。一个程序可以包含多个线程&#xff0c;每个线程代表一个独立的执行路径&#xff0c;使得程序可以并发地处理多个任务。 线程的基本概念 线程与进程的区别&#xff1a; 进程是资源分配的单位&…

SSH实验5密钥登录Linuxroot用户(免密登录)

当用户尝试通过SSH连接到远程服务器时&#xff0c;客户端会生成一对密钥&#xff1a;公钥和私钥。公钥被发送到远程服务器&#xff0c;并存储在服务器的~/.ssh/authorized_keys文件中。而私钥则由客户端保管&#xff0c;不会传输给服务器。 在连接过程中&#xff0c;客户端使用…

域名邮箱推荐:安全与稳定的邮件域名邮箱!

域名邮箱推荐及绑定攻略&#xff1f;最好用的域名邮箱服务推荐&#xff1f; 域名邮箱&#xff0c;作为一种个性化且专业的电子邮件服务&#xff0c;越来越受到企业和个人的青睐。烽火将详细介绍域名邮箱登录的全过程&#xff0c;从注册到登录&#xff0c;帮助您轻松掌握这一重…

政治经济学笔记

【拯救者】政治经济学速成&#xff08;基础习题&#xff09; 研究生产关系必须联系生产力和上层建筑 1.生产力与生产关系 生产力代表生产的物质内容&#xff0c;生产关系是生产的社会形式。生产力决定生产关系&#xff0c;生产关系对生产力具有 反作用 *其中的”反作用”指的是…

《TCP/IP网络编程》学习笔记 | Chapter 7:优雅地断开套接字连接

《TCP/IP网络编程》学习笔记 | Chapter 7&#xff1a;优雅地断开套接字连接 《TCP/IP网络编程》学习笔记 | Chapter 7&#xff1a;优雅地断开套接字连接基于 TCP 的半关闭单方面断开连接带来的问题套接字和流针对优雅断开的 shutdown 函数为何需要半关闭&#xff1f;基于半关闭…

python | 包

1. 在python中什么是包&#xff1f; ​ 包是一种组织代码的方式&#xff0c;如下图所示红色部分目录mypackage就称为一个包&#xff0c;它之所以称为一个包完全是因为它里面有蓝色方框里的文件__init__.py。 ​ 这个目录被定义为一个包之后&#xff0c;我们就可以通过import来…