请教:多线程同时写socket是否需要加锁

socket的write/send还是是否是线程安全? 在多线程的网络服务器程序中, 对同一个客户端多线程同时发送数据是经常可能发生的事情, 也就是有可能会多 线程的对一个fd调用send/write, 那么这种操作是否需要加锁?并发写套接字是否导致系统缓冲区数据混乱呢? 网上搜 了下,有人说可以写,有人说不能,linux man page也没有说明。 看来需要写程序测试。 写了个server的代码进行 测试。 10个线程同时对一个fd进行 阅读详情


第一种可以,因为Socket是双工的


多线程读写同一Socket的话基本上是会出问题的
想要不出问题的话,除非你的多个线程作用是一样的








在TCP/TP卷2中有这样的结构体
struct sockbuf{


short sb_flags;
..........
}so_recv,so_snd;
其中flag 有这几种标志:
SB_LOCK;一个进程已经锁定了插口缓存
SB_WANT;一个进程正在等待给插口缓存加锁.


还有些宏和函数来管理插口的发送缓存和接收缓存
sblock,  sbunlock, sbwait(page 388,389)
也就是说感觉socket内部其实已经考虑到了这点,我们应用的时候是否只需要
一些操着比如设置一些标志位或者一些宏?






继续翻了下send 的实现,
发现了有如下代码:


if(error = sblock(&so->so_snd, SBLOCKWAIT(flag)))   
         goto  out;
do{


.......


}


函数在发送的时候,首先会对缓存加锁.通过加锁确保多个进程按序互斥访问插口缓存.(tcp/ip 卷2, page 394,395)
也就是说其实系统已经帮我们做好这些了.






多线程写socket应该要加锁,而且要保证返回值等于要发送的数据长度或出错后才能解锁。虽然内核在写一个文件时可能会


自动加锁,但是如果socket缓冲区不足以容纳下用户的所有数据的话,线程要进入睡眠状态,这时系统是否会解锁跟实现有


关吧






应该对socket加锁。 尤其是对非阻塞的socket,底层对缓冲区加锁并不能解决数据交错的问题。




我想flw2 是想让你在 send_n 的时候加锁
虽然系统send 是原子的..但不保证 send_n是原子的..所以要加锁以保证 线程A send_n完后.
线程B再send_n .




我刚学网络编程的时候也傻到给socket加锁,后来用代码验证是不需要加锁的:lol:




一般都是多个工作线程把需要发送的数据写到一个加锁的缓冲区中,然后另外一个线程单独进行收发。多个线程直接写


socket还真没这么做过。我觉得应该是加锁处理,并且需要判断已发送字节数等于发送字节数才成。




需要加锁。 除非单一线程发送




把这个贴子再顶起来,因为我今天刚好碰到了这个问题。用多个线程写一个套接口,读据在应用层肯定是混在一起的,比如


线程t1要写100个'a',线程t2要写100个'b',那么实际上对方接收到的数据是a、b混杂的,这就一点意义也没有了。有人说


write是原子的,但是我们一般用的都是writen吧,很少调用一次write不管结果如何都返回的。可以结贴了吧,呵呵


对SOCKET的写操作从用户的角度并不是原子的,因为如果一次发送1M数据,肯定不是原子的.至于一次发送多少会是原子的,好


像没有明确的说法 (最好不要去做原子性的假设) (和MTU是没有关系的,那是底层的分包)




归根结底好像有两个结论:


1.避免多个线程同时对一个socket进行操作。


2.如果是在无法避免上述情况,则应该加锁。


是否正确?






如果需要多个线程同时读访问或写访问同一个tcp socket, 那多半是程序设计上出了问题。


对于tcp的传输,都是要用应用层的协议保证接收方能解释对方发送过来的数据,这样,至少要保证一块数据是一个完整的协


议包。


如果是多个线程同时写socket,那么在临界区里工作的线程为了保证数据包的完整发送,必须循环发送等待,直到数据都发


送到系统缓冲区才能离开临界区。
而这样就导致socket的行为与阻塞方式发送无异,发送效率因此而被限制。


我觉得一个好的tcp socket处理框架,应该是只有一个线程来负责数据的收发,从而避免那些无穷无尽的同步问题。






如果需要多个线程同时读访问或写访问同一个tcp socket, 那多半是程序设计上出了问题。


对于tcp的传输,都是要用应用层的协议保证接收方能解释对方发送过来的数据,这样,至少要保证一块数据是一个完整的协


议 ... 


正解!






其实这种情况很常见,为什么说是设计的问题?
举个例子:
一个porxy服务器,一边连接客户端,一边连接服务端的80端口.对于每个客户的连接处理为一个线程,收到客户消息转发到服务


器.




PROXY, 对于CLIENT的一个连接,就建立一个到SERVER的连接.
所以,混杂的情况是没有的.


不同的FLOW的包混在一个LINK中是设计出问题了.






如果需要多个线程同时读访问或写访问同一个tcp socket, 那多半是程序设计上出了问题。


对于tcp的传输,都 ...


同意
多线程send ,,写文件,发送管道 多线程文件操作 阅读详情

相关推荐

两个线程对socket 进行读和写,需要加锁吗

我给你用讲清楚👇。

谢谢大家的关注和点赞!这里只有纯纯的知识干货,没有一句废话。希望能实实在在帮到大家~要是觉得有用,别忘了给我点支持哟,你 480

Socket套接字在多线程发送数据时要加锁吗

Socket套接字在多线程发送数据时要加锁吗 1)对于 UDP,多线程读写同一个 socket 不用加锁,不过更好的做法是每个线程有自己的 socket,避免 contention,可以用 SO_REUSEPORT 来实现这一点; 2)对于 TCP,通常多线程读写同一个 socket 是错误的设计,因为有 short write 的可能。假如你加锁,而又发生 short write,你是不是要一直...

kevin_org 1620

基于Python适用于YOLO目标检测算法的图片数据增强处理

为了增强模型的鲁棒性以及数据的丰富性,同 时为了防止由于数据过少发生过拟合,本设计对数 据集进行数据增强处理,包括随机亮度调节、随机 对比度调节、随机饱和度调节、加入高斯噪声、水 平翻转、运动模糊和旋转 15°

weixin_67136409的博客 699

多线程问题:为什么不应该使用多线程读写同一个socket连接?

为什么不应该使用多线程读写一个socket连接

weixin_45685193的博客 7302

RK3308B开发板WiFi+蓝牙一体模组RTL8821CS驱动移植保姆级教程(含DTS配置与避坑点)

本文提供RK3308B开发板RTL8821CS WiFi+蓝牙模组驱动移植的完整教程,涵盖SDK环境配置、DTS设备树设置、内核编译优化及功能验证全流程。重点解析引脚复用冲突、电源管理等关键配置,并给出常见错误解决方案,帮助开发者快速实现双模通信功能。

weixin_42531163的博客 398

芯片测试中的DC与AC模式详解:如何选择最适合你的测试方案?

本文深入解析了芯片测试中DC(直流)与AC(交流)模式的核心差异与互补性。DC测试关注静态电气特性,如固定型故障;而AC测试则聚焦于芯片在额定工作速度下的动态时序行为。文章从VLSI设计、电路模块、成本约束、可测试性设计和应用场景五大维度,提供了如何根据工艺节点、工作频率及具体需求,在testMode配置、时钟复位策略和输入输出接口设计中,平衡两种测试模式以制定最优方案的决策框架。

bb456的博客 1086

多线程同时写socket是否需要加锁(转)

[打印] [订阅] [收藏] [推荐给朋友] [本帖文本页] yuangong 精灵

3468

VLSI数字信号处理系统——第九章滤波器和变换中的算法强度缩减

[课程学习] VLSI数字信号处理系统——第九章滤波器和变换中的算法强度缩减

夏风喃喃的博客 1604

linux的write是线程安全的吗,socket的write/send还是是否是线程安全?

在多线程的网络服务器程序中, 对同一个客户端多线程同时发送数据是经常可能发生的事情, 也就是有可能会多线程的对一个fd调用send/write, 那么这种操作是否需要加锁?并发写套接字是否导致系统缓冲区数据混乱呢? 网上搜了下,有人说可以写,有人说不能,linux man page也没有说明。 看来需要写程序测试。 写了个server的代码进行测试。10个线程同时对一个fd进行write, 看看客...

weixin_39616880的博客 733

IEEE ACCESS Please note that all author names should be listed in English.(所有作者名需用英文名列出)

很奇怪哈,我明明手稿和提交页面作者都是用的英文,但是为什么还是会提示我没用英文呢?后来给编辑发消息,回的很快,他给我发了一个截图,确实是出现中文,但是我还是不知道为啥会出现中文。直到晚上回寝室洗澡的时候忽然想起来了是不是orcid的原因,因为它会强制作者绑定一个orcid账号,而我的orcid账号的名字刚好是中文的。当然这个只是我的一个猜想,但是我觉得可能性很大。我的第二篇论文已经投稿了快三个月了,效果非常的不好,所以我打算转投IEEE ACCESS了,希望这里可以给我一点好的建议。

kuyecsl的博客 3310

YOLO26升级:CVPR2026 WDAM小波方向注意力+C2PSA,频域高频引导低频暗区复原,小目标检测精度跃升!

将 WDAM 引入 YOLO 的 C2PSA 模块,核心优势在于用极低的计算开销,为模型装上了一个“结构感知”的增强器,尤其适合处理密集小目标与边缘部署场景。

①答疑群聊服务;②YOLO大模型知识问答系统;③计算机视觉论文生成智能体; 369

socket套接字在多线程发送数据时要加锁吗?

转自知乎问题:一条报文在1000字节到4000字节之间,数据量在每秒5000左右,多线程写套接字,要加锁吗?没有加锁会导致报文错乱吗?在网络编程的时候,报文不超过MTU是否就无需对套接字加锁?解答①:你连 UDP 还是 TCP 都没说。对于 UDP,多线程读写同一个 socket 不用加锁,不过更好的做法是每个线程有自己的 socket,避免 contention,可以用 SO_REUSEPORT...

hemeinvyiqiluoben的专栏 9131

AutoSAR配置视频讲解:简介

AutoSAR实验视频讲解:闪烁一颗LED实验【简介】 大家好,欢迎来到雪云飞星的《AutoSAR实验课的视频讲解》专栏。看过《AutoSAR入门到精通系列讲解》的朋友们应该对博主不陌生,有很多朋友加了博主的微信成为了好友,还有朋友约过线下见面,博主很高兴大家能从我的博客中获得一些收获。在专栏里博主挖了很多坑,当时也说过想要录制一个AutoSAR的配置视频教程,素材在20年初就已经录好,中间各种原因足足鸽了一年。当时因为一些技术原因只能通过博客的图文形式展示出来,现在我们剪辑了视频,请了专业的配音,希望以视

雪云飞星的博客 9652

Socket套接字在多线程发送数据时要加锁吗?

转自知乎 问题:一条报文在1000字节到4000字节之间,数据量在每秒5000左右,多线程写套接字,要加锁吗?没有加锁会导致报文错乱吗?在网络编程的时候,报文不超过MTU是否就无需对套接字加锁? 解答①: 你连 UDP 还是 TCP 都没说。 对于 UDP,多线程读写同一个 socket 不用加锁,不过更好的做法是每个线程有自己的 socket,避免 contention,可以用 SO_R...

zxh2075的专栏 3318

五、实战pxe安装ubuntu 22.04 软raid1(实际生产pxe配置)

这段配置文件是一个cloud-init的自动安装配置,用于自动化部署Ubuntu服务器操作系统。它定义了从系统身份、键盘布局、区域设置到磁盘分区和RAID配置的一系列设置,并且包含了在安装过程的最后阶段执行的一些命令。基础设置version: 1指定了autoinstall配置文件的版本。source定义了安装源,这里是ubuntu-server。identity设置了主机名(hostname)、用户(username)和密码(password注意这里的密码是经过加密的。键盘与语言设置。

jundao1997的专栏 999

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

对于socket发送数据时是否要加锁及write read的阻塞非阻塞

偶尔讨论到了socket发送数据时是否应该加锁的问题,就在网上查了一下,下面是大神陈硕的答案 对于 UDP,多线程读写同一个 socket 不用加锁,不过更好的做法是每个线程有自己的 socket,避免 contention,可以用 SO_REUSEPORT 来实现这一点。 对于 TCP,通常多线程读写同一个 socket 是错误的设计,因为有 short write 的可能。假如你加...

weixin_34357887的博客 1102

怀旧版电脑GBC模拟器

再现原版GBC掌机的界面,电脑运行连游戏界面都一样大小,很怀旧,很真实,(英文版)强烈推荐,很小的文件,很难才找到的。

多线程 socket

MFC下使用CSocket或者CAsyncSocket进行Socket通信,CSocket继承自 CAsyncSocket。这两者的区别在于,CSocket是同步的Socket,CAsyncSocket则是异步的。使用时,CSocket::Receive()和CSocket::Send()函数会阻塞当前线程,直至操作完成;而 CAsyncSocket::Receive()和CAsyncSocket

pedoming的专栏 5407

廖雪峰Python教程[完整版]

廖雪峰的python教程整理的,已经排好版了,而且还是完整的,适合小白

深度学习工具包 DeepLearningToolbox

深度学习工具包Deprecation notice.-----This toolbox is outdated and no longer maintained.There are much better tools available for deep learning than this toolbox, e.g. [Theano](http://deeplearning.net/software/theano/), [torch](http://torch.ch/) or [tensorflow](http://www.tensorflow.org/)I would suggest you use one of the tools mentioned above rather than use this toolbox.Best, Rasmus.DeepLearnToolbox================A Matlab toolbox for Deep Learning.Deep Learning is a new subfield of machine learning that focuses on learning deep hierarchical models of data.It is inspired by the human brain's apparent deep (layered, hierarchical) architecture.A good overview of the theory of Deep Learning theory is[Learning Deep Architectures for AI](http://www.iro.umontreal.ca/~bengioy/papers/ftml_book.pdf)For a more informal introduction, see the following videos by Geoffrey Hinton and Andrew Ng.* [The Next Generation of Neural Networks](http://www.youtube.com/watch?v=AyzOUbkUf3M) (Hinton, 2007)* [Recent Developments in Deep Learning](http://www.youtube.com/watch?v=VdIURAu1-aU) (Hinton, 2010)* [Unsupervised Feature Learning and Deep Learning](http://www.youtube.com/watch?v=ZmNOAtZIgIk) (Ng, 2011)If you use this toolbox in your research please cite [Prediction as a candidate for learning deep hierarchical models of data](http://www2.imm.dtu.dk/pubdb/views/publication_details.php?id=6284)```@MASTERSTHESIS\{IMM2012-06284, author = "R. B. Palm", title = "Prediction as a candidate for learning deep hierarchical models of data", year = "2012",}```Contact: rasmusbergpalm at gmail dot comDirectories included in the toolbox-----------------------------------`NN/` - A library for Feedforward Backpropagation Neural Networks`CNN/` - A library for Convolutional Neural Networks`DBN/` - A library for Deep Belief Networks`SAE/` - A library for Stacked Auto-Encoders`CAE/` - A library for Convolutional Auto-Encoders`util/` - Utility functions used by the libraries`data/` - Data used by the examples`tests/` - unit tests to verify toolbox is workingFor references on each library check REFS.mdSetup-----1. Download.2. addpath(genpath('DeepLearnToolbox'));Example: Deep Belief Network---------------------```matlabfunction test_example_DBNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit RBM and visualize its weightsrand('state',0)dbn.sizes = [100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);figure; visualize(dbn.rbm{1}.W'); % Visualize the RBM weights%% ex2 train a 100-100 hidden unit DBN and use its weights to initialize a NNrand('state',0)%train dbndbn.sizes = [100 100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);%unfold dbn to nnnn = dbnunfoldtonn(dbn, 10);nn.activation_function = 'sigm';%train nnopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.10, 'Too big error');```Example: Stacked Auto-Encoders---------------------```matlabfunction test_example_SAEload mnist_uint8;train_x = double(train_x)/255;test_x = double(test_x)/255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit SDAE and use it to initialize a FFNN% Setup and train a stacked denoising autoencoder (SDAE)rand('state',0)sae = saesetup([784 100]);sae.ae{1}.activation_function = 'sigm';sae.ae{1}.learningRate = 1;sae.ae{1}.inputZeroMaskedFraction = 0.5;opts.numepochs = 1;opts.batchsize = 100;sae = saetrain(sae, train_x, opts);visualize(sae.ae{1}.W{1}(:,2:end)')% Use the SDAE to initialize a FFNNnn = nnsetup([784 100 10]);nn.activation_function = 'sigm';nn.learningRate = 1;nn.W{1} = sae.ae{1}.W{1};% Train the FFNNopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.16, 'Too big error');```Example: Convolutional Neural Nets---------------------```matlabfunction test_example_CNNload mnist_uint8;train_x = double(reshape(train_x',28,28,60000))/255;test_x = double(reshape(test_x',28,28,10000))/255;train_y = double(train_y');test_y = double(test_y');%% ex1 Train a 6c-2s-12c-2s Convolutional neural network %will run 1 epoch in about 200 second and get around 11% error. %With 100 epochs you'll get around 1.2% errorrand('state',0)cnn.layers = { struct('type', 'i') %input layer struct('type', 'c', 'outputmaps', 6, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %sub sampling layer struct('type', 'c', 'outputmaps', 12, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %subsampling layer};cnn = cnnsetup(cnn, train_x, train_y);opts.alpha = 1;opts.batchsize = 50;opts.numepochs = 1;cnn = cnntrain(cnn, train_x, train_y, opts);[er, bad] = cnntest(cnn, test_x, test_y);%plot mean squared errorfigure; plot(cnn.rL);assert(er<0.12, 'Too big error');```Example: Neural Networks---------------------```matlabfunction test_example_NNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);% normalize[train_x, mu, sigma] = zscore(train_x);test_x = normalize(test_x, mu, sigma);%% ex1 vanilla neural netrand('state',0)nn = nnsetup([784 100 10]);opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samples[nn, L] = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.08, 'Too big error');%% ex2 neural net with L2 weight decayrand('state',0)nn = nnsetup([784 100 10]);nn.weightPenaltyL2 = 1e-4; % L2 weight decayopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex3 neural net with dropoutrand('state',0)nn = nnsetup([784 100 10]);nn.dropoutFraction = 0.5; % Dropout fraction opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex4 neural net with sigmoid activation functionrand('state',0)nn = nnsetup([784 100 10]);nn.activation_function = 'sigm'; % Sigmoid activation functionnn.learningRate = 1; % Sigm require a lower learning rateopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex5 plotting functionalityrand('state',0)nn = nnsetup([784 20 10]);opts.numepochs = 5; % Number of full sweeps through datann.output = 'softmax'; % use softmax outputopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex6 neural net with sigmoid activation and plotting of validation and training error% split training data into training and validation datavx = train_x(1:10000,:);tx = train_x(10001:end,:);vy = train_y(1:10000,:);ty = train_y(10001:end,:);rand('state',0)nn = nnsetup([784 20 10]); nn.output = 'softmax'; % use softmax outputopts.numepochs = 5; % Number of full sweeps through dataopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, tx, ty, opts, vx, vy); % nntrain takes validation set as last two arguments (optionally)[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');```[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/rasmusbergpalm/deeplearntoolbox/trend.png)](https://bitdeli.com/free "Bitdeli Badge")

socket多线程编程

socket多线程编程实现并发服务器 一、多线程简介 1、什么是线程? 线程在操作系统原理中是这样描述的:线程是进程的一条执行路径。线程在Unix系统下,通常被称为轻量级的进程,线程虽然不是进程,但却可以看作是Unix进程的表亲,所有的线程都是在同一进程空间运行,这也意味着多条线程将共享该进程中的全部系统资源,如虚拟地址空间,文件描述符和信号处理等等。但同一进程中的多个线程有各自的调用栈(call stack),自己的寄存器环境(register context),自己的线程本地存储(thread-l

King_的博客 4802

多线程socket编程的注意事项

在socket编程中,如果有多个线程公用一个方法去发送数据时,注意对该方法的加锁保护,因为多线程容易造成数据包的破坏,可能引起连接的中断或者数据的破坏等未知情况!

PI2024的专栏 898

使用libevent进行多线程socket编程demo

最近要对一个用libevent写的C/C++项目进行修改,要改成多线程的,故做了一些学习和研究。 libevent是一个用C语言写的开源的一个库。它对socket编程里的epoll/select等功能进行了封装,并且使用了一些设计模式(比如反 应堆模式),用事件机制来简化了socket编程。libevent的好处网上有很多,但是初学者往往都看不懂。我打个比方吧, 1) 假设有N个客户端同时往

zixi2015的专栏 2468

socket多线程

socket多线程

weixin_53331739的博客 2687

面试加分题--socket是否是并发安全的?

面试加分题--socket是否是并发安全的?

技术专家 923

c语言socket多线程模版,pthread多线程(C语言) + Socket

pthread多线程(C语言) + Socketpthread是使用使用C语言编写的多线程的API, 简称Pthreads ,是线程的POSIX标准,可以在Unix / Linux / Windows 等系统跨平台使用。在类Unix操作系统(Unix、Linux、Mac OS X等)中,都使用Pthreads作为操作系统的线程。GitHub项目FanSocket(纯C语言socket+线程队列)+...

weixin_31845811的博客 571
上一篇: AMR文件格式分析
下一篇: Socket那些事——winsocket日记(1)
flymachine
博客等级 码龄23年 253粉丝 34原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值