鸿蒙开发实战:【网络管理-Socket连接】

介绍

本示例主要演示了Socket在网络通信方面的应用,展示了Socket在两端设备的连接验证、聊天通信方面的应用。

效果预览

使用说明

1.打开应用,点击用户文本框选择要登录的用户,并输入另一个设备的IP地址,点击确定按钮进入已登录的用户页面(两个设备都要依次执行此步骤)。

2.在其中一个设备上点击创建房间按钮,任意输入房间号,另一个设备会收到有房间号信息的弹框,点击确定按钮后,两个设备进入聊天页面。

3.在其中一个设备上输入聊天信息并点击发送按钮后,另一个设备的聊天页面会收到该聊天消息。

4.点击顶部标题栏右侧的退出图标按钮,则返回已登录的用户页面。

5.点击聊天页面中的昵称栏,会弹出一个菜单,选择离线选项后,两端设备的状态图标都会切换为离线图标,并且昵称栏都会变成灰色,此时任何一端发送消息另一端都接收不到消息。

6.当点击昵称栏再次切换为在线状态,则两端的己方账号状态会切换为在线图标,同时两端的昵称栏会显示蓝色,此时可正常收发消息。

工程目录

entry/src/main/ets/MainAbility
|---app.ets
|---model
|   |---chatBox.ts                     // 聊天页面
|   |---DataSource.ts                  // 数据获取
|   |---Logger.ts                      // 日志工具
|---pages
|   |---Index.ets                      // 监听消息页面
|   |---Login.ets                      // 首页登录页面
|---Utils
|   |---Utils.ets

具体实现

  • 本示例分为三个模块
    • 输入对端IP模块
      • 使用wifi.getIpInfo()方法获取IP地址,constructUDPSocketInstance方法创建一个UDPSocket对象
      • 源码链接:[Login.ets]
/** Copyright (c) 2022-2023 Huawei Device Co., Ltd.* Licensed under the Apache License, Version 2.0 (the "License");* you may not use this file except in compliance with the License.* You may obtain a copy of the License at**     http://www.apache.org/licenses/LICENSE-2.0** Unless required by applicable law or agreed to in writing, software* distributed under the License is distributed on an "AS IS" BASIS,* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.* See the License for the specific language governing permissions and* limitations under the License.*/import wifi from '@ohos.wifi';
import router from '@ohos.router';
import { resolveIP } from '../Utils/Util'
import socket from '@ohos.net.socket';
import Logger from '../model/Logger'const TAG: string = '[Login]'let localAddr = {address: resolveIP(wifi.getIpInfo().ipAddress),family: 1,port: 0
}
let oppositeAddr = {address: '',family: 1,port: 0
}
let loginCount = 0let udp = socket.constructUDPSocketInstance()@Entry
@Component
struct Login {@State login_feng: boolean = false@State login_wen: boolean = false@State user: string = ''@State roomDialog: boolean = false@State confirmDialog: boolean = false@State ipDialog: boolean = true@State warnDialog: boolean = false@State warnText: string = ''@State roomNumber: string = ''@State receiveMsg: string = ''bindOption() {let bindOption = udp.bind(localAddr);bindOption.then(() => {Logger.info(TAG, 'bind success');}).catch(err => {Logger.info(TAG, 'bind fail');})udp.on('message', data => {Logger.info(TAG, `data:${JSON.stringify(data)}`);let buffer = data.message;let dataView = new DataView(buffer);Logger.info(TAG, `length = ${dataView.byteLength}`);let str = '';for (let i = 0;i < dataView.byteLength; ++i) {let c = String.fromCharCode(dataView.getUint8(i));if (c != '') {str += c;}}if (str == 'ok') {router.clear();loginCount += 1;router.push({url: 'pages/Index',params: { address: oppositeAddr.address, port: oppositeAddr.port, loginCount: loginCount }})}else {this.receiveMsg = str;this.confirmDialog = true;}})}build() {Stack({ alignContent: Alignment.Center }) {Column() {Text($r('app.string.MainAbility_label')).width('100%').height(50).backgroundColor('#0D9FFB').textAlign(TextAlign.Start).fontSize(25).padding({ left: 10 }).fontColor(Color.White).fontWeight(FontWeight.Bold)if (!this.ipDialog) {Column() {Image(this.login_feng ? $r('app.media.fengziOn') : $r('app.media.wenziOn')).width(100).height(100).objectFit(ImageFit.Fill)Text('用户名:' + this.user).fontSize(25).margin({ top: 50 })Button() {Text($r('app.string.create_room')).fontSize(25).fontColor(Color.White)}.width('150').height(50).margin({ top: 30 }).type(ButtonType.Capsule).onClick(() => {this.roomDialog = truethis.bindOption()})}.width('90%').margin({ top: 100 })}}.width('100%').height('100%')if (this.confirmDialog) {Column() {Text('确认码:' + this.receiveMsg).fontSize(25)Row() {Button($r('app.string.cancel')).onClick(() => {this.confirmDialog = false}).backgroundColor(0xffffff).fontColor(Color.Black)Button($r('app.string.confirm')).onClick(() => {udp.send({data: 'ok',address: oppositeAddr}).then(function (data) {Logger.info(TAG, `send ${JSON.stringify(data)}`);}).catch(function (err) {Logger.info(TAG, `send ${JSON.stringify(err)}`);})router.clear()loginCount += 1;router.push({url: 'pages/Index',params: { address: oppositeAddr.address, port: oppositeAddr.port, loginCount: loginCount }})this.confirmDialog = false;}).backgroundColor(0xffffff).fontColor(Color.Red)}.margin({ bottom: 10 }).justifyContent(FlexAlign.SpaceAround)}.width('80%').height(150).margin({ top: '10%' }).backgroundColor(Color.White).border({ radius: 10, width: 3 })}if (this.ipDialog) {Column() {Text('本地IP:' + localAddr.address).fontSize(25).margin({ top: 10 })Text('用户:' + this.user).fontSize(20).margin({ top: 10 }).bindMenu([{value: '风子',action: () => {this.user = '风子'this.login_feng = truethis.login_wen = falselocalAddr.port = 8080oppositeAddr.port = 9090}},{value: '蚊子',action: () => {this.user = '蚊子'this.login_wen = truethis.login_feng = falselocalAddr.port = 9090oppositeAddr.port = 8080}}])TextInput({ placeholder: '请输入对端ip' }).width(200).fontSize(25).margin({ top: 10 }).onChange((value: string) => {oppositeAddr.address = value;})if (this.warnDialog) {Text(this.warnText).fontSize(10).fontColor(Color.Red).margin({ top: 5 })}Button($r('app.string.confirm')).fontColor(Color.Black).height(30).margin({ bottom: 10 }).onClick(() => {if (this.user == '') {this.warnDialog = true;this.warnText = '请先选择用户';} else if (oppositeAddr.address === '') {this.warnDialog = true;this.warnText = '请先输入对端IP';} else {this.bindOption()this.ipDialog = false;Logger.debug(TAG, `peer ip=${oppositeAddr.address}`);Logger.debug(TAG, `peer port=${oppositeAddr.port}`);Logger.debug(TAG, `peer port=${localAddr.port}`);}}).backgroundColor(0xffffff)}.width('80%').height(200).margin({ top: '10%' }).backgroundColor(Color.White).border({ radius: 10, width: 3 })}if (this.roomDialog) {Column() {Text($r('app.string.input_roomNumber')).fontSize(25).margin({ top: 10 })TextInput().width(100).fontSize(25).margin({ top: 10 }).onChange((value: string) => {this.roomNumber = value;})Row() {Button($r('app.string.cancel')).onClick(() => {this.roomDialog = false}).backgroundColor(0xffffff).fontColor(Color.Black)Button($r('app.string.confirm')).onClick(() => {Logger.info(TAG, `[ROOM]address=${oppositeAddr.address}`);Logger.info(TAG, `[ROOM]port=${oppositeAddr.port}`);/*点击确定后发送房间号,另一端开始监听*/Logger.info(TAG, `[ROOM]oppositeAddr.address=${oppositeAddr.address}`);Logger.info(TAG, `[ROOM]oppositeAddr.port=${oppositeAddr.port}`);Logger.info(TAG, `[ROOM]localAddr.address=${localAddr.address}`);Logger.info(TAG, `[ROOM]localAddr.port=${localAddr.port}`);this.bindOption()udp.send({data: this.roomNumber,address: oppositeAddr}).then(function (data) {Logger.info(TAG, `send success, data = ${JSON.stringify(data)}`);}).catch(function (err) {Logger.info(TAG, `send fail, err = ${JSON.stringify(err)}`);})this.roomDialog = false;}).backgroundColor(0xffffff).fontColor(Color.Red)}.margin({ bottom: 10 }).justifyContent(FlexAlign.SpaceAround)}.width('80%').height(150).margin({ top: '10%' }).backgroundColor(Color.White).border({ radius: 10, width: 3 })}}}
}

[Util.ets]

/** Copyright (c) 2022-2023 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* 
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.*/export function resolveIP(ip) {
if (ip < 0 || ip > 0xFFFFFFFF) {
throw ('The number is not normal!');
}
return (ip >>> 24) + '.' + (ip >> 16 & 0xFF) + '.' + (ip >> 8 & 0xFF) + '.' + (ip & 0xFF);
}
  • 创建房间模块
    • 点击创建房间按钮,弹出创建房间框,输入房间号,点击确定,进入聊天页面
    • 源码链接:[Login.ets]
/** Copyright (c) 2022-2023 Huawei Device Co., Ltd.* Licensed under the Apache License, Version 2.0 (the "License");* you may not use this file except in compliance with the License.* You may obtain a copy of the License at**     http://www.apache.org/licenses/LICENSE-2.0** Unless required by applicable law or agreed to in writing, software* distributed under the License is distributed on an "AS IS" BASIS,* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.* See the License for the specific language governing permissions and* limitations under the License.*/import wifi from '@ohos.wifi';
import router from '@ohos.router';
import { resolveIP } from '../Utils/Util'
import socket from '@ohos.net.socket';
import Logger from '../model/Logger'const TAG: string = '[Login]'let localAddr = {address: resolveIP(wifi.getIpInfo().ipAddress),family: 1,port: 0
}
let oppositeAddr = {address: '',family: 1,port: 0
}
let loginCount = 0let udp = socket.constructUDPSocketInstance()@Entry
@Component
struct Login {@State login_feng: boolean = false@State login_wen: boolean = false@State user: string = ''@State roomDialog: boolean = false@State confirmDialog: boolean = false@State ipDialog: boolean = true@State warnDialog: boolean = false@State warnText: string = ''@State roomNumber: string = ''@State receiveMsg: string = ''bindOption() {let bindOption = udp.bind(localAddr);bindOption.then(() => {Logger.info(TAG, 'bind success');}).catch(err => {Logger.info(TAG, 'bind fail');})udp.on('message', data => {Logger.info(TAG, `data:${JSON.stringify(data)}`);let buffer = data.message;let dataView = new DataView(buffer);Logger.info(TAG, `length = ${dataView.byteLength}`);let str = '';for (let i = 0;i < dataView.byteLength; ++i) {let c = String.fromCharCode(dataView.getUint8(i));if (c != '') {str += c;}}if (str == 'ok') {router.clear();loginCount += 1;router.push({url: 'pages/Index',params: { address: oppositeAddr.address, port: oppositeAddr.port, loginCount: loginCount }})}else {this.receiveMsg = str;this.confirmDialog = true;}})}build() {Stack({ alignContent: Alignment.Center }) {Column() {Text($r('app.string.MainAbility_label')).width('100%').height(50).backgroundColor('#0D9FFB').textAlign(TextAlign.Start).fontSize(25).padding({ left: 10 }).fontColor(Color.White).fontWeight(FontWeight.Bold)if (!this.ipDialog) {Column() {Image(this.login_feng ? $r('app.media.fengziOn') : $r('app.media.wenziOn')).width(100).height(100).objectFit(ImageFit.Fill)Text('用户名:' + this.user).fontSize(25).margin({ top: 50 })Button() {Text($r('app.string.create_room')).fontSize(25).fontColor(Color.White)}.width('150').height(50).margin({ top: 30 }).type(ButtonType.Capsule).onClick(() => {this.roomDialog = truethis.bindOption()})}.width('90%').margin({ top: 100 })}}.width('100%').height('100%')if (this.confirmDialog) {Column() {Text('确认码:' + this.receiveMsg).fontSize(25)Row() {Button($r('app.string.cancel')).onClick(() => {this.confirmDialog = false}).backgroundColor(0xffffff).fontColor(Color.Black)Button($r('app.string.confirm')).onClick(() => {udp.send({data: 'ok',address: oppositeAddr}).then(function (data) {Logger.info(TAG, `send ${JSON.stringify(data)}`);}).catch(function (err) {Logger.info(TAG, `send ${JSON.stringify(err)}`);})router.clear()loginCount += 1;router.push({url: 'pages/Index',params: { address: oppositeAddr.address, port: oppositeAddr.port, loginCount: loginCount }})this.confirmDialog = false;}).backgroundColor(0xffffff).fontColor(Color.Red)}.margin({ bottom: 10 }).justifyContent(FlexAlign.SpaceAround)}.width('80%').height(150).margin({ top: '10%' }).backgroundColor(Color.White).border({ radius: 10, width: 3 })}if (this.ipDialog) {Column() {Text('本地IP:' + localAddr.address).fontSize(25).margin({ top: 10 })Text('用户:' + this.user).fontSize(20).margin({ top: 10 }).bindMenu([{value: '风子',action: () => {this.user = '风子'this.login_feng = truethis.login_wen = falselocalAddr.port = 8080oppositeAddr.port = 9090}},{value: '蚊子',action: () => {this.user = '蚊子'this.login_wen = truethis.login_feng = falselocalAddr.port = 9090oppositeAddr.port = 8080}}])TextInput({ placeholder: '请输入对端ip' }).width(200).fontSize(25).margin({ top: 10 }).onChange((value: string) => {oppositeAddr.address = value;})if (this.warnDialog) {Text(this.warnText).fontSize(10).fontColor(Color.Red).margin({ top: 5 })}Button($r('app.string.confirm')).fontColor(Color.Black).height(30).margin({ bottom: 10 }).onClick(() => {if (this.user == '') {this.warnDialog = true;this.warnText = '请先选择用户';} else if (oppositeAddr.address === '') {this.warnDialog = true;this.warnText = '请先输入对端IP';} else {this.bindOption()this.ipDialog = false;Logger.debug(TAG, `peer ip=${oppositeAddr.address}`);Logger.debug(TAG, `peer port=${oppositeAddr.port}`);Logger.debug(TAG, `peer port=${localAddr.port}`);}}).backgroundColor(0xffffff)}.width('80%').height(200).margin({ top: '10%' }).backgroundColor(Color.White).border({ radius: 10, width: 3 })}if (this.roomDialog) {Column() {Text($r('app.string.input_roomNumber')).fontSize(25).margin({ top: 10 })TextInput().width(100).fontSize(25).margin({ top: 10 }).onChange((value: string) => {this.roomNumber = value;})Row() {Button($r('app.string.cancel')).onClick(() => {this.roomDialog = false}).backgroundColor(0xffffff).fontColor(Color.Black)Button($r('app.string.confirm')).onClick(() => {Logger.info(TAG, `[ROOM]address=${oppositeAddr.address}`);Logger.info(TAG, `[ROOM]port=${oppositeAddr.port}`);/*点击确定后发送房间号,另一端开始监听*/Logger.info(TAG, `[ROOM]oppositeAddr.address=${oppositeAddr.address}`);Logger.info(TAG, `[ROOM]oppositeAddr.port=${oppositeAddr.port}`);Logger.info(TAG, `[ROOM]localAddr.address=${localAddr.address}`);Logger.info(TAG, `[ROOM]localAddr.port=${localAddr.port}`);this.bindOption()udp.send({data: this.roomNumber,address: oppositeAddr}).then(function (data) {Logger.info(TAG, `send success, data = ${JSON.stringify(data)}`);}).catch(function (err) {Logger.info(TAG, `send fail, err = ${JSON.stringify(err)}`);})this.roomDialog = false;}).backgroundColor(0xffffff).fontColor(Color.Red)}.margin({ bottom: 10 }).justifyContent(FlexAlign.SpaceAround)}.width('80%').height(150).margin({ top: '10%' }).backgroundColor(Color.White).border({ radius: 10, width: 3 })}}}
}

[Util.ets]

/** Copyright (c) 2022-2023 Huawei Device Co., Ltd.* Licensed under the Apache License, Version 2.0 (the "License");* you may not use this file except in compliance with the License.* You may obtain a copy of the License at**     http://www.apache.org/licenses/LICENSE-2.0** Unless required by applicable law or agreed to in writing, software* distributed under the License is distributed on an "AS IS" BASIS,* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.* See the License for the specific language governing permissions and* limitations under the License.*/export function resolveIP(ip) {if (ip < 0 || ip > 0xFFFFFFFF) {throw ('The number is not normal!');}return (ip >>> 24) + '.' + (ip >> 16 & 0xFF) + '.' + (ip >> 8 & 0xFF) + '.' + (ip & 0xFF);
}
相关概念

UDP Socket是面向非连接的协议,它不与对方建立连接,而是直接把我要发的数据报发给对方,适用于一次传输数据量很少、对可靠性要求不高的或对实时性要求高的应用场景。

相关权限

1.允许使用Internet网络权限:[ohos.permission.INTERNET]

2.允许应用获取WLAN信息权限:[ohos.permission.GET_WIFI_INFO]

依赖

不涉及。

约束与限制

1.本示例仅支持标准系统上运行,支持设备:RK3568。

2.本示例仅支持API9版本SDK,版本号:3.2.11.9 及以上。

3.本示例需要使用DevEco Studio 3.1 Beta2 (Build Version: 3.1.0.400 构建 2023年4月7日)及以上才可编译运行。

下载

如需单独下载本工程,执行如下命令:

git init
git config core.sparsecheckout true
echo code\BasicFeature\Connectivity\Socket > .git/info/sparse-checkout
git remote add origin https://gitee.com/openharmony/applications_app_samples.git
git pull origin master

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

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

相关文章

【C++】用红黑树模拟实现set、map

目录 前言及准备&#xff1a;一、红黑树接口1.1 begin1.2 end1.3 查找1.4 插入1.5 左单旋和右单旋 二、树形迭代器&#xff08;正向&#xff09;2.1 前置 三、模拟实现set四、模拟实现map 前言及准备&#xff1a; set、map的底层结构是红黑树&#xff0c;它们的函数通过调用红…

鸿蒙Harmony应用开发—ArkTS声明式开发(基础手势:Toggle)

组件提供勾选框样式、状态按钮样式及开关样式。 说明&#xff1a; 该组件从API Version 8开始支持。后续版本如有新增内容&#xff0c;则采用上角标单独标记该内容的起始版本。 子组件 仅当ToggleType为Button时可包含子组件。 接口 Toggle(options: { type: ToggleType, is…

一台电脑安装多个版本node,如何切换使用

直接上答案&#xff0c;请安装nvm——nodejs的版本管理工具 官网地址在此&#xff1a;nvm文档手册 - nvm是一个nodejs版本管理工具 - nvm中文网 (uihtm.com) 1.由于我电脑本来就有node14&#xff0c;所以需要先卸载 原来的node&#xff0c;建议在软件目录自带的node文件夹中点…

[Java、Android面试]_08_强软弱虚四种引用及应用场景

本人今年参加了很多面试&#xff0c;也有幸拿到了一些大厂的offer&#xff0c;整理了众多面试资料&#xff0c;后续还会分享众多面试资料。 整理成了面试系列&#xff0c;由于时间有限&#xff0c;每天整理一点&#xff0c;后续会陆续分享出来&#xff0c;感兴趣的朋友可关注收…

电机驱动器不确定性建模

跟踪误差信号和执行器驱动信号在控制系统的设计中也很重要&#xff01;&#xff01;&#xff01; 不确定度可分为扰动信号和动态扰动两类。前者包括输入和输出干扰&#xff08;如飞机上的阵风&#xff09;、传感器噪声和执行器噪声等。后者表示数学模型与系统在运行中的实际动…

Geostationary IR Channel Brightness Temperature - GridSat B1 -- shell下载

进入网页 https://www.ncei.noaa.gov/products/gridded-geostationary-brightness-temperature 然后进入数据目录&#xff0c;通过https的方式进行下载&#xff1a; 点击后进入如下界面&#xff1a; 点击任意年份进行下载 这里以2004年为例&#xff0c;如下所示&#xff1…

【CSS练习】万年历 html+css+js

效果图 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8" /><meta name"viewport" content"widthdevice-width, initial-scale1.0" /><title>Document</title><style>bod…

实现:mysql-5.7.42 到 mysql-8.2.0 的升级(二进制方式)

实现&#xff1a;mysql-5.7.42 到 mysql-8.2.0 的升级&#xff08;二进制方式&#xff09; 1、操作环境1、查看当前数据库版本2、操作系统版本3、查看 Linux 系统上的 glibc&#xff08;GNU C 库&#xff09;版本&#xff08;**这里很重要&#xff0c;要下载对应的内核mysql版本…

Linux 进程管理工具top ps

概述 top 和 ps 是 Linux 系统中两个非常重要的用于管理和监控进程的命令工具。以下是它们的主要功能和区别&#xff1a; top&#xff1a; 动态视图&#xff1a;top 提供了一个实时动态更新的视图&#xff0c;能够持续显示系统中当前正在运行的进程信息及其资源占用情况。 系统…

注意力机制 self-attention 的原理探究

一、点积的认识 向量的点积可以表示相似性的原因在于它衡量了两个向量之间的方向是否相似。当两个向量的方向趋于一致时&#xff0c;它们的点积会更大&#xff1b;当两个向量的方向趋于相互垂直时&#xff0c;它们的点积会接近于0。这种性质使得点积在衡量向量之间的相似性和相…

ins中扰动分析举例

扰动分析很重要&#xff0c;搞明白扰动分析&#xff0c;基本上就可以清楚了误差模型。 什么是扰动分析&#xff1a; 简单理解 测量值 真值 误差 这里的误差就是与测量直接对应的误差&#xff0c;例如 把误差分离出来 误差 测量值 - 真值 &#xff…

Docker基本配置及使用

Docker基本配置及使用 使用步骤 1.卸载旧版 代码如下&#xff1a;首先如果系统中已经存在旧的Docker&#xff0c;则先卸载 yum remove docker \docker-client \docker-client-latest \docker-common \docker-latest \docker-latest-logrotate \docker-logrotate \docker-engin…

网站首页添加JS弹屏公告窗口教程

很多小白站长会遇到想给自己的网站添加一个弹屏公告&#xff0c;用于做活动说明、演示站提示等作用与目的。 下面直接上代码&#xff1a;&#xff08;直接复制到网页头部、底部php、HTML文件中&#xff09; <script src"https://www.mohuda.com/site/js/sweetalert.m…

0基础学习VR全景平台篇第145篇:图层控件功能

大家好&#xff0c;欢迎观看蛙色VR官方——后台使用系列课程&#xff01;这期&#xff0c;我们将为大家介绍如何使用图层控件功能。 一.如何使用图层控件功能&#xff1f; 进入作品编辑页面&#xff0c;点击左边的控件后就可以在右边进行相应设置。 二.图层控件有哪些功能&am…

款海韵-650LX:电流参数是最大电流!

其实&#xff0c;在选择电源时&#xff0c;不需要担心峰值功率和额定功率。 您只需检查参数是否与您相应部件的功率匹配即可。 1.首先需要了解各个参数的含义。 电源上有5个电压参数&#xff0c;分别是12V、5V、3.3V、5VSB、-12V。 12V为CPU、显卡和机械硬盘的电机部分供电。 …

Linux课程_____用户的管理

一、规则 用户至少属于一个组,在创建时如果不指定组,将会创建同名的组 用户只能有一个基本组(主组),但可以隶属于多个附加组 如果一个组作为某用户的基本组,此组将不能被删除 UID: 用户标识 GID: 组的标识 root管理员的uid及gid 都为0 二、用户的配置文件 1./etc/passwd …

3/19作业

select实现的TCP并发服务器 #include <myhead.h> #define SER_PORT 8888 #define SER_IP "192.168.47.130"int main(int argc, const char *argv[]) {int sfd -1;sfd socket(AF_INET,SOCK_STREAM,0);if(sfd -1){perror("socket");return -1;}pri…

resize-observer源码解读

resize-observer github 地址&#xff1a;https://github.com/devrelm/resize-observer 本地启动 npm installnpm startnode 18.16.0 (npm 9.5.1) 启动失败报错 node:internal/crypto/hash:71this[kHandle] new _Hash(algorithm, xofLen);^Error: error:0308010C:digital …

【Py/Java/C++三种语言OD2023C卷真题】20天拿下华为OD笔试之【模拟】2023C-攀登者2【欧弟算法】全网注释最详细分类最全的华为OD真题题解

有LeetCode算法/华为OD考试扣扣交流群可加 948025485 可上全网独家的 欧弟OJ系统 练习华子OD、大厂真题 绿色聊天软件戳 od1336了解算法冲刺训练 文章目录 题目描述与示例题目描述输入描述输出描述 示例输入输出 解题思路原路返回和非原路返回原路返回走过的总路程从左边空地出…

流畅的Python(二十一)-类元编程

一、核心要义 1.类元编程时指在运行时创建或定制类的技艺 2.类是一等对象,因此任何时候都可以使用函数新建类&#xff0c;而无需使用class关键字 3.类装饰器也是函数&#xff0c;不过能够审查、修改&#xff0c;甚至把被装饰的类替换为其它类。 4.元类(type类的子类)类编程…