利用Delphi编写Socket通信程序.docx

上传人:牧羊曲112 文档编号:2078224 上传时间:2023-01-07 格式:DOCX 页数:36 大小:113.80KB
返回 下载 相关 举报
利用Delphi编写Socket通信程序.docx_第1页
第1页 / 共36页
利用Delphi编写Socket通信程序.docx_第2页
第2页 / 共36页
利用Delphi编写Socket通信程序.docx_第3页
第3页 / 共36页
利用Delphi编写Socket通信程序.docx_第4页
第4页 / 共36页
利用Delphi编写Socket通信程序.docx_第5页
第5页 / 共36页
点击查看更多>>
资源描述

《利用Delphi编写Socket通信程序.docx》由会员分享,可在线阅读,更多相关《利用Delphi编写Socket通信程序.docx(36页珍藏版)》请在三一办公上搜索。

1、Indy10Install All packages are followed by X0 (Where X is your Delphi verison).1. Download source from the Development Snapshot. Delphi / BCB Installation1. Open and compile in the following order: 2.1. IndySystem (in LibSystem) 2. IndyCore (in LibCore) 3. IndyProtocols (in LibProtocols) 4. IndySupe

2、rCore (in LibSuperCore)If you are not using SuperCore, then you do not need to compile this package. 3. Now open and click install in the following order 4.5.1. dclIndyCore (in LibCore) 2. dclIndyProtocols (in LibProtocols) 3. dclSuperCore (in LibSuperCore)Only install this if you have compiled Supe

3、rCore. 利用Delphi编写Socket通信程序2004-08-24 人气:5925 出处:csdn 作者: dudunono 原作 一、Delphi与Socket计算机网络是由一系列网络通信协议组成的,其中的核心协议是传输层的TCP/IP和UDP协议。TCP是面向连接的,通信双方保持一条通路,好比目前的电话线,使用telnet登陆BBS,用的就是TCP协议;UDP是无连接的,通信双方都不保持对方的状态,浏览器访问Internet时使用的HTTP协议就是基于UDP协议的。TCP和UDP协议都非常复杂,尤其是TCP协议,为了保证网络传输的正确性和有效性,必须进行一系列复杂的纠错和排序等处理

4、。Socket是建立在传输层协议(主要是TCP和UDP)上的一种套接字规范,最初是由美国加州Berkley大学提出,它定义两台计算机间进行通信的规范(也是一种编程规范),如果说两台计算机是利用一个“通道“进行通信,那么这个“通道“的两端就是两个套接字。套接字屏蔽了底层通信软件和具体操作系统的差异,使得任何两台安装了TCP协议软件和实现了套接字规范的计算机之间的通信成为可能。微软的Windows Socket规范(简称winsock)对Berkley的套接字规范进行了扩展,利用标准的Socket的方法,可以同任何平台上的Socket进行通信;利用其扩展,可以更有效地实现在Windows平台上计算

5、机间的通信。在Delphi中,其底层的Socket也应该是Windows的Socket。Socket减轻了编写计算机间通信软件的难度,但总的说来还是相当复杂的(这一点在后面具体会讲到);Inprise在Delphi中对Windows Socket进行了有效的封装,使得用户可以很方便地编写网络通信程序。下面我们实例解读在Delphi中如何利用Socket编写通信程序。二、利用Delphi编写Socket通信程序。下面是一个简单的Socket通信程序,其中客户机和服务机是同一个程序,当客户机(服务器)在一个memo1中输入一段文字然后敲入回车,该段文字就可以显示在服务器(客户机)的memo2中,反

6、之亦成立。具体步骤如下:1、新建一个form,任意命名,不妨设之为chatForm;放上一个MainMenu(在Standard栏中),建立ListenItem、ConnectItem、Disconnect和Exit菜单项;在从Internet栏中选择TServerSocket、TClientSocket添加到chatForm中,其中把TClientSocket的名字设为ClientSocket, port设为1025,默认的active为false;把TServerSocket的名字设为ServerSocket,port设为1025,默认的active为false,其他的不变;再放入两个me

7、mo,一个命名为memo1,另外一个命名为memo2,其中把memo2的color设置为灰色,因为主要用来显示对方的输入。下面我们一边编写代码一边解释原因。、双击ListemItem。写入如下代码:procedure TChatForm.ListenItemClick(Sender: TObject);beginListenItem.Checked := not ListenItem.Checked;if ListenItem.Checked thenbeginClientSocket.Active := False;ServerSocket.Active := True;endelsebeg

8、inif ServerSocket.Active thenServerSocket.Active := False;end;end;该程序段的说明如下:当用户选择ListemItem时,该ListenItem取反,如果选中的话,说明处于Listen状态,读者要了解的是:listen是Socket作为Server时一个专有的方法,如果处于listen,则ServerSocket设置为活动状态;否则,取消listen,则关闭ServerSocket。实际上,只有用户一开始选择该菜单项,表明该程序用作Server。反之,如果用户选择ConnectItem,则必然作为Client使用。、双击Conne

9、ctItem,敲入以下代码。procedure TChatForm.ConnectItemClick(Sender: TObject);beginif ClientSocket.Active then ClientSocket.Active := False;if InputQuery(Computer to connect to, Address Name:, Server) thenif Length(Server) 0 thenwith ClientSocket dobeginHost := Server;Active := True;ListenItem.Checked := Fals

10、e;end;end;这段程序的主要功能就是当用户选择ConnectItem菜单项时,设置应用程序为客户机,弹出input框,让用户输入服务器的地址。这也就是我们不一开始固定ClientSocket的host的原因,这样用户可以动态地连接不同的服务器。读者需要了解的是主机地址只是Socket作为客户机时具有的一个属性,Socket作为服务器时“一般“不用地址,因为它同本机绑定。4、在memo1的keydown方法中写入如下代码:procedure TChatForm.Memo1KeyDown(Sender: TObject; var Key: Word;Shift: TShiftState);b

11、eginif Key = VK_Return thenif IsServer thenServerSocket.Socket.Connections0.SendText(Memo1.LinesMemo1.Lines.Count - 1)elseClientSocket.Socket.SendText(Memo1.LinesMemo1.Lines.Count - 1);end;该段代码的作用很明显,就是开始发消息了。其中如果是Server的话,它只向第一个客户机发消息,由于一个服务器可以连接多个客户机,而同客户机的每一个连接都由一个Socket来维持,因此ServerSocket.Socket.

12、Connnections数组中存储的就是同Client维持连接的Socket。在标准Socket中,服务器方的Socket通过accept()方法的返回值获取维持同客户机连接的Socket,而发送、接受消息的方法分别为send(sendto)和recv(recvfrom), Delphi对此进行了封装。、其余代码的简要介绍。procedure TChatForm.ServerSocketAccept(Sender: TObject;Socket: TCustomWinSocket);beginIsServer := True;end;ServerSocket的Accept方法,当客户机第一次连

13、接时完成,通过其参数可以认为,它是在标准的accept方法后执行的,因为有TCustomWinSocket这个参数类型,它应该是标准Server方Socket的返回值。 procedure TChatForm.ClientSocketRead(Sender: TObject;Socket: TCustomWinSocket);beginMemo2.Lines.Add(Socket.ReceiveText);end;procedure TChatForm.ServerSocketClientRead(Sender: TObject;Socket: TCustomWinSocket);beginM

14、emo2.Lines.Add(Socket.ReceiveText);end;这两段代码分别是服务器方和客户机方在收到对方的消息时,由Delphi触发的,作用是在memo2中显示收到的消息。其中,ClientSocketRead中的Socket实际上就是Socket本身,而在ServerSocketClientRead中的Socket实际上是ServerSocket.Socket.Connection中的某个Socket。不过在Delphi中,对服务器方的Socket进行了有效的封装。procedure TChatForm.ServerSocketClientConnect(Sender: T

15、Object;Socket: TCustomWinSocket);beginMemo2.Lines.Clear;end;procedure TChatForm.ClientSocketDisconnect(Sender: TObject;Socket: TCustomWinSocket);beginListenItemClick(nil);end;这两段比较简单。其中ServerSocketClientConnect在ServerSocket收到一个新的连接时触发。而ClientSocketDisconnect在ClientSocket发出Disconncet时触发。procedure TCh

16、atForm.Exit1Click(Sender: TObject);beginServerSocket.Close;ClientSocket.Close;Close;end;procedure TChatForm.Disconnect1Click(Sender: TObject);beginClientSocket.Active := False;ServerSocket.Active := True;end;第一段为关闭应用程序。在标准Socket中,每个Socket在关闭时,必须调用closesocket()方法,否则系统不会释放资源。而在ServerSockt.Close和Client

17、Socket.Close中,系统内部肯定调用了closesocket()方法。三、标准Socket与Delphi中的Socket。标准的Socket的应用程序框架如下:Server方: Socket() 新建一个SocketBind() 同服务器地址邦定 Listen() Accept()block waitread()接受消息,在windows平台中,方法为send(TCP),或者是sendto(UDP)处理服务请求Write()发送消息,在windows平台中,方法为send(TCP), 或者为sendto(UDP)。Client方相对简单:Socket()Connect()通过一定的po

18、rt连接特定的服务器,这是与服务器建立连接Write()Read()。Socket可以是基于TCP的,也可以是基于UDP,同时Socket甚至建立在其他的协议,比如IPX/SPX,DECNet等。在新建一个Socket时,可以指定新建何类Socket。Bind()用来同服务器的地址邦定,如果一个主机只有一个IP地址,实际上邦定的作用就相对多余了。Listen()开始监听网络,Accept()用于接受连接,其返回值是保持同客户机联系的Socket。在Delphi中,对于Windows中的Socket进行了有效的封装。在Delphi中,按其继承关系,可以分层两类:一、TComponentTAbst

19、ractSocketTCustomSocketTCustomServerSocketTServerSocketTComponentTAbstractSocketTCustomSocketTClientSocket二、直接从TObject继承过来:TObjectTCustomWinSocketTServerWinSocketTObjectTCustomWinSocketTClientWinSocketTObjectTCustomWinSocketTServerClientWinSocket可以看出第一类建立在TCustomSocket基础上,第二类建立在TCustomWinSocket的基础上。

20、第一类建立在TComponet的基础上,第二类直接构建在TObject基础上。因此如果用户非常熟悉Socket并且想要编写控制台程序时,可以使用TCustomWinScoket类。同uses中可以看出,它们都在ScktComp.pas中实现,而在schtComp.pas中,则包含了winsock.pas文件,如果继续深入winsock文件,在其中可以发现所有的Windows Socket的基本方法。实际上,如果你了解了标准Socket的应用程序框架,对于使用Delphi编写Socket应用程序也就得心应手了;这不是说你必须了解复杂的Socket中的标准函数,也没有必要,因为Delphi已经为你

21、做了很好的封装了,这也正是Delphi的强势所在,你只要了解那么一点点的基本框架。这是我对Delphi中的Socket应用的理解,不足之处希望大家指正。同时也乐于为大家解答Delphi中有关Socket的问题。用Indy组件开发Socket应用程序 创建时间:2004-3-16文章属性:转载文章提交:绝对零度今日浏览:23总共次数:648 文章作者:虚度文章出处:yesky 笔者在前一段的工作中,需要开发一套简单的网络数据传输程序。由于平时常用Delphi做点开发,故此次也不例外。Delphi 7中带有两套TCP Socket组件:Indy Socket组件(IdTCPClient和IdTCP

22、Server)和Delphi原生的TCP Socket组件(ClientSocket和ServerSocket)。但是,Borland已宣称ClientSocket和ServerSocket组件即将被废弃,建议用相应的Indy组件来代替。因此,笔者使用了Indy。本文在对Indy进行简要介绍的基础上,创建了一组简单的TCP Socket数据传输应用来演示了Indy的使用方法。开放源代码的Internet组件集Internet Direct(Indy)Internet Direct(Indy)是一组开放源代码的Internet组件,涵盖了几乎所有流行的Internet协议。Indy用Delphi

23、编写,被包含在Delphi 6,Kylix 1和C+ Builder 6及以上各个版本的Borland开发环境中。Indy曾经叫做WinShoes(双关于WinSockWindows的Socket库),是由Chad Z. Hower领导的一群开发者构建的,可以从Indy的站 10也进入了Beta测试阶段。Delphi 7中所带的是Indy 9。在其的组件面板上,一共安装有100多个Indy组件。使用这些组件你可以开发基于各种协议的TCP客户和服务器应用程序,并处理相关的编码和安全问题。你可以通过前缀Id来识别Indy组件。Indy是阻塞式(Blocking)的当你使用Winsock开发网络应用

24、程序时,从Socket中读取数据或者向Socket写入数据都是异步发生的,这样就不会阻断程序中其它代码的执行。在收到数据时,Winsock会向应用程序发送相应的消息。这种访问方式被称作非阻塞式连接,它要求你对事件作出响应,设置状态机,并通常还需要一个等待循环。与通常的Winsock编程方法不同的是,Indy使用了阻塞式Socket调用方式。阻塞式访问更像是文件存取。当你读取数据,或是写入数据时,读取和写入函数将一直等到相应的操作完成后才返回。比如说,发起网络连接只需调用Connect方法并等待它返回,如果该方法执行成功,在结束时就直接返回,如果未能成功执行,则会抛出相应的异常。同文件访问不同的

25、是,Socket调用可能会需要更长的时间,因为要读写的数据可能不会立即就能准备好(在很大程度上依赖于网络带宽)。阻塞式Socket并非恶魔(Evil)长期以来,阻塞式Socket都遭到了毫无理由的攻击。其实阻塞式Socket并非如通常所说的那样可怕。这还要从Winsock的发展说起。当Socket被从Unix移植到Windows时,一个严重的问题立即就出现了。Unix支持fork,客户程序和服务器都能够fork新的进程,并启动这些进程,从而能够很方便地使用阻塞式Socket。而Windows 3.x既不支持fork也不支持多线程,当使用阻塞式Socket时,用户界面就会被“锁住”而无法响应用户

26、输入。为克服Windows 3.x的这一缺陷,微软在Winsock中加入了异步扩展,以使Winsock不会“锁住”应用程序的主线程(也是唯一的线程)。然而,这需要了一种完全不同的编程方式。于是有些人为了掩饰这一弱点,就开始强烈地诽谤阻塞式Socket。当Win32出现的时候,它能够很好地支持线程。但是既成的观念已经很难更改,并且说出去的话也无法收回,因此对阻塞式Socket的诽谤继续存在着。事实上,阻塞式Socket仍然是Unix实现Socket的唯一方式,并且它工作得很好。阻塞式Socket的优点归结起来,在Windows上使用阻塞式Socket开发应用程序具有如下优点:编程简单阻塞式Soc

27、ket应用程序很容易编写。所有的用户代码都写在同一个地方,并且顺序执行。 容易向Unix移植由于Unix也使用阻塞式Socket,编写可移植的代码就变得比较容易。Indy就是利用这一点来实现其多平台支持而又单一源代码的设计。 很好地利用了线程技术阻塞式Socket是顺序执行的,其固有的封装特性使得它能够很容易地使用到线程中。 阻塞式Socket的缺点事物都具有两面性,阻塞式Socket也不例外。它的一个主要的缺点就是使客户程序的用户界面“冻结”。当在程序的主线程中进行阻塞式Socket调用时,由于要等待Socket调用完成并返回,这段时间就不能处理用户界面消息,使得Update、Repaint

28、以及其它消息得不到及时响应,从而导致用户界面被“冻结”。使用TIdAntiFreeze对抗“冻结”Indy使用一个特殊的组件TIdAntiFreeze来透明地解决客户程序用户界面“冻结”的问题。TIdAntiFreeze在Indy内部定时中断对栈的调用,并在中断期间调用Application.ProcessMessages方法处理消息,而外部的Indy调用继续保存阻塞状态,就好像TIdAntiFreeze对象不存在一样。你只要在程序中的任意地方添加一个TIdAntiFreeze对象,就能在客户程序中利用到阻塞式Socket的所有优点而避开它的一些显著缺点。Indy使用了线程技术阻塞式Socek

29、t通常都采用线程技术,Indy也是如此。从最底层开始,Indy的设计都是线程化的。因此用Indy创建服务器和客户程序跟在Unix下十分相似,并且Delphi的快速开发环境和Indy对WinSock的良好封装使得应用程序创建更加容易。Indy服务器模型一个典型的Unix服务器有一个或多个监听进程,它们不停地监听进入的客户连接请求。对于每一个需要服务的客户,都fork一个新进程来处理该客户的所有事务。这样一个进程只处理一个客户连接,编程就变得十分容易。Indy服务器工作原理同Unix服务器十分类似,只是Windows不像Unix那样支持fork,而是支持线程,因此Indy服务器为每一个客户连接分配

30、一个线程。图1显示了Indy服务器的工作原理。Indy服务器组件创建一个同应用程序主线程分离的监听线程来监听客户连接请求,对于接受的每一个客户,都创建一个新的线程来为该客户提供服务,所有与这一客户相关的事务都由该线程来处理。使用组件TIdThreadMgrPool,Indy还支持线程池。 上一页 1 2 3 4 下一页线程与Indy客户程序Indy客户端组件并未使用线程。但是在一些高级的客户程序中,程序员可以在自定义的线程中使用Indy客户端组件,以使用户界面更加友好。简单的Indy应用示例下面将创建一个简单的TCP客户程序和一个简单的TCP服务器来演示Indy的基本使用方法。客户程序使用TC

31、P协议同服务器连接,并向服务器发送用户所输入数据。服务器支持两条命令:DATA和QUIT。在DATA命令后跟随要发送的数据,并用空格将命令字DATA和数据分隔开。表单布局建立一个项目组,添加一个客户程序项目和一个服务器项目。客户程序和服务器程序的表单布局如同2和图3所示。客户程序表单上放置了TIdTCPClient组件,服务器程序表单上放置了TIdTCPServer组件。为防止客户程序“冻结”,还在其表单上放置TIdAntiFreeze组件。客户程序和服务器程序的表单上都放置有TListBox组件,用来显示通信记录。客户程序代码客户程序片断如代码列表1所示。代码列表1procedure TFo

32、rmMain.BtnConnectClick(Sender: TObject);beginIdTCPClient.Host := EdtHost.Text;IdTCPClient.Port := StrToInt(EdtPort.Text);LbLog.Items.Add(正在连接 + EdtHost.Text + .);with IdTCPClient dobegintryConnect(5000);tryLbLog.Items.Add(ReadLn();BtnConnect.Enabled := False;BtnSend.Enabled := True;BtnDisconnect.Ena

33、bled := True;exceptLbLog.Items.Add(远程主机无响应!);IdTCPClient.Disconnect();end;/end tryexceptLbLog.Items.Add(无法建立到 + EdtHost.Text + 的连接!);end;/end tryend;/end withend;procedure TFormMain.BtnSendClick(Sender: TObject);beginLbLog.Items.Add(DATA + EdtData.Text);with IdTCPClient dobegintryWriteLn(DATA + EdtD

34、ata.Text);LbLog.Items.Add(ReadLn()exceptLbLog.Items.Add(发送数据失败!);IdTCPClient.Disconnect();LbLog.Items.Add(同主机 + EdtHost.Text + 的连接已断开!);BtnConnect.Enabled := True;BtnSend.Enabled := False;BtnDisconnect.Enabled := False;end;/end tryend;/end withend;procedure TFormMain.BtnDisconnectClick(Sender: TObje

35、ct);varReceived: string;beginLbLog.Items.Add(QUIT);tryIdTCPClient.WriteLn(QUIT);finallyIdTCPClient.Disconnect();LbLog.Items.Add(同主机 + EdtHost.Text + 的连接已断开!);BtnConnect.Enabled := True;BtnSend.Enabled := False;BtnDisconnect.Enabled := False;end;/end tryend; 在“连接”按钮事件响应过程中,首先根据用户输入设置IdTCPClient的主机和端口

36、,并调用IdTCPClient的Connect方法向服务器发出连接请求。然后调用ReadLn方法读取服务器应答数据。在“发送”按钮事件响应过程中,调用WriteLn方法写DATA命令,向服务器发送数据。在“断开”按钮事件响应过程中,向服务器发送QUIT命令,并调用Disconnect方法断开连接。程序中还包含有通信信息记录和异常处理的代码。服务器程序代码服务器程序片断如代码列表2所示。代码列表2procedure TFormMain.BtnStartClick(Sender: TObject);beginIdTCPServer.DefaultPort := StrToInt(EdtPort.T

37、ext);IdTCPServer.Active := True;BtnStart.Enabled := False;BtnStop.Enabled := True;LbLog.Items.Add(服务器已成功启动!);end;procedure TFormMain.BtnStopClick(Sender: TObject);beginIdTCPServer.Active := False;BtnStart.Enabled := True;BtnStop.Enabled := False;LbLog.Items.Add(服务器已成功停止!);end;procedure TFormMain.IdT

38、CPServerConnect(AThread: TIdPeerThread);beginLbLog.Items.Add(来自主机 + AThread.Connection.Socket.Binding.PeerIP+ 的连接请求已被接纳!);AThread.Connection.WriteLn(100: 欢迎连接到简单TCP服务器!);end;procedure TFormMain.IdTCPServerExecute(AThread: TIdPeerThread);varsCommand: string;beginwith AThread.Connection dobeginsComman

39、d := ReadLn();FLogEntry := sCommand + 来自于主机 + AThread.Connection.Socket.Binding.PeerIP;AThread.Synchronize(AddLogEntry);if AnsiStartsText(DATA , sCommand) thenbeginFReceived := RightStr(sCommand, Length(sCommand)-5);WriteLn(200: 数据接收成功!);AThread.Synchronize(DisplayData);endelse if SameText(sCommand,

40、 QUIT) then beginFLogEntry := 断开同主机 + AThread.Connection.Socket.Binding.PeerIP+ 的连接!;AThread.Synchronize(AddLogEntry);Disconnect;endelse beginWriteLn(500: 无法识别的命令!);FLogEntry := 无法识别命令: + sCommand;AThread.Synchronize(AddLogEntry);end;/endifend;end;procedure TFormMain.DisplayData();beginEdtData.Text

41、:= FReceived;end;procedure TFormMain.AddLogEntry();beginLbLog.Items.Add(FLogEntry);end; “启动”按钮设置IdTCPServer 的Active属性为True来启动服务器,“停止”按钮设置Active属性为False来关闭服务器。IdTCPServerConnect方法作为IdTCPServer 的OnCorrect事件响应过程,向客户端发送欢迎信息。OnCorrect事件在一个客户连接请求被接受时发生,为该连接创建的线程AThread被作为参数传递给IdTCPServerConnect方法。IdTCPSer

42、verExecute方法是IdTCPServer 的OnExecute事件响应过程。OnExecute事件在TIdPeerThread对象试图执行其Run方法时发生。OnExecute事件与通常的事件有所不同,其响应过程是在某个线程上下文中执行的,参数AThread就是调用它的线程。这一点很重要,它意味着可能有多个OnExecute事件响应过程被同时执行。在连接被断开或中断前,OnExecute事件响应过程会被反复执行。在IdTCPServerExecute方法中,首先读入一条指令,然后对指令进行判别。如果是DATA指令,就解出数据并显示它。如果收到的是QUIT指令,则断开连接。需要特别指出的

43、是,由于IdTCPServerExecute方法在某一线程上下文中执行,因此显示数据和添加事件记录都是将相应的方法传递给Synchronize调用来完成的。运行程序运行客户端和服务器程序,按如下流程进行操作:1. 按服务器程序的“启动”按钮启动服务器;2. 按客户程序的“连接”按钮,建立同服务器的连接;3. 在客户程序的待发送数据编辑框中输入“Hello, Indy!”,并按“发送”按钮发送数据;4. 按客户程序的“断开”按钮,断开同服务器的连接;5. 按服务器程序的“停止”按钮停止服务器。 用Socket接收和转换数字和字符串数据【大 中 小】【打印】【加入收藏】【关闭】浏览字号:日期:20

44、05-06-13 人气:60 出处: 作者: 7nightlove 很多时候远程系统在执行并发任务的时候,会把它接收到数据的长度以数字的形式发送出去。但用socket发送和接收数字型数据的时候,要考虑到一个问题:要根据网络另一端机器的类型转换数据。尤其需要知道怎样把要发送的数据格式(网络格式)从本地机器的格式(主机格式)转换成为行业标准格式。 使用IPAddress.NetworkToHostOrder可以把数据从网络规则转换为主机格式,下面的ReceiveHeader函数说明了它的用法,ReceiveHeader函数实现过程如下:1 用Socket.Receive从远程机器接收数据。 2 验

45、证接收到的字节数是4。3 Socket.Receive返回一个字节型数组,BitConvert.ToInt32把它转换成数字型数值。4 最后,IPAddress.NetworkToHostOrder把长数值转换为主机格式。public int ReceiveHeader(Socket socket) int dataSize = -1; / error byte buffer = new byte4; int bytesRead = socket.Receive(buffer, 4, System.Net.Sockets.SocketFlags.None); if (4 = bytesRead) dataSize = BitConverter.ToInt32(buffer, 0); dataSize = IPA

展开阅读全文
相关资源
猜你喜欢
相关搜索
资源标签

当前位置:首页 > 生活休闲 > 在线阅读


备案号:宁ICP备20000045号-2

经营许可证:宁B2-20210002

宁公网安备 64010402000987号