1)sendBuf(),sendText(),sendStream()

几乎所有的通信控件都会提供上面的3个方法。首先看看SendBuf()。

function TCustomWinSocket.SendBuf(var Buf; Count: Integer): Integer;
var
ErrorCode: Integer;
begin
Lock;
try
Result := 0;
if not FConnected then Exit;
Result := send(FSocket, Buf, Count, 0);
if Result = SOCKET_ERROR then
begin
ErrorCode := WSAGetLastError;
if (ErrorCode <> WSAEWOULDBLOCK) then
begin
Error(Self, eeSend, ErrorCode);
Disconnect(FSocket);
if ErrorCode <> 0 then
raise ESocketError.CreateResFmt(@sWindowsSocketError,
[SysErrorMessage(ErrorCode), ErrorCode, 'send']);
end;
end;
finally
Unlock;
end;
end;

Result := send(FSocket, Buf, Count, 0); // 发送指定一块指定大小的缓存数据,指定多大就发送多大,但一般不会超过32K的大小,至于太大的数据要如何处理,后面会作出讲解。

接下来看下sendText()。

function TCustomWinSocket.SendText(const s: AnsiString): Integer;
begin
Result := SendBuf(Pointer(S)^, Length(S) * SizeOf(AnsiChar));
end;

原来是调用的sendBuf(),代码就不作解释。

最后看sendStream()。

function TCustomWinSocket.SendStream(AStream: TStream): Boolean;
begin
Result := False;
if FSendStream = nil then
begin
FSendStream := AStream;
Result := SendStreamPiece;
end;
end;

调用了SendStreamPiece()。

function TCustomWinSocket.SendStreamPiece: Boolean;
var
Buffer: array[0..4095] of Byte;
StartPos: Integer;
AmountInBuf: Integer;
AmountSent: Integer;
ErrorCode: Integer;

procedure DropStream;
begin
if FDropAfterSend then Disconnect(FSocket);
FDropAfterSend := False;
FSendStream.Free;
FSendStream := nil;
end;

begin
Lock;
try
Result := False;
if FSendStream <> nil then
begin
if (FSocket = INVALID_SOCKET) or (not FConnected) then exit;
while True do
begin
StartPos := FSendStream.Position;
AmountInBuf := FSendStream.Read(Buffer, SizeOf(Buffer));
if AmountInBuf > 0 then
begin
AmountSent := send(FSocket, Buffer, AmountInBuf, 0);
if AmountSent = SOCKET_ERROR then
begin
ErrorCode := WSAGetLastError;
if ErrorCode <> WSAEWOULDBLOCK then
begin
Error(Self, eeSend, ErrorCode);
Disconnect(FSocket);
DropStream;
if FAsyncStyles <> [] then Abort;
Break;
end else
begin
FSendStream.Position := StartPos;
Break;
end;
end else if AmountInBuf > AmountSent then
FSendStream.Position := StartPos + AmountSent
else if FSendStream.Position = FSendStream.Size then
begin
DropStream;
Break;
end;
end else
begin
DropStream;
Break;
end;
end;
Result := True;
end;
finally
Unlock;
end;
end;

大的数据,一般超过32K,就用sendStream()发送,先将数据一次性加载进流对象中,然后每次从流中读取4k大小的数据进一个内存块中,然后通过SOCKET发送这个内存块。

到这里不免会产生几个疑问。

大数据为什么要分割成4K的小块分作几次传送?

一是小块传输增加了数据传输的可靠性,二是无形中增加了服务端的并发能力。

那么服务端是怎么接收和处理客户端分割传输的数据?

这里就涉及到"粘包“这个概念了,服务端先创建一个流对象,将每次收到的小块数据依次地写进流对象中,在写之前流的POSITION+数据块的长度,这样通过流对象将这些小块数据合并还原成一个完整的数据。

socket发送和接收数据的更多相关文章

  1. [Socket网络编程]由于套接字没有连接并且(当使用一个 sendto 调用发送数据报套接字时)没有提供地址,发送或接收数据的请求没有被接受。

    原文地址:http://blog.sina.com.cn/s/blog_70bf579801017ylu.html,记录在此方便查看 解决办法: MSDN的说明: Close 方法可关闭远程主机连接, ...

  2. socket 错误之:OSError: [WinError 10057] 由于套接字没有连接并且(当使用一个 sendto 调用发送数据报套接字时)没有提供地址,发送或接收数据的请求没有被接受。

    出错的代码 #server端 import socket import struct sk=socket.socket() sk.bind(('127.0.0.1',8080)) sk.listen( ...

  3. Netty——高级发送和接收数据handler处理器

    netty发送和接收数据handler处理器 主要是继承 SimpleChannelInboundHandler 和 ChannelInboundHandlerAdapter 一般用netty来发送和 ...

  4. netty发送和接收数据handler处理器

    netty发送和接收数据handler处理器 主要是继承 SimpleChannelInboundHandler 和 ChannelInboundHandlerAdapter 一般用netty来发送和 ...

  5. udp网络程序-发送、接收数据

    1. udp网络程序-发送数据 创建一个基于udp的网络程序流程很简单,具体步骤如下: 创建客户端套接字 发送/接收数据 关闭套接字 代码如下: #coding=utf-8from socket im ...

  6. 手把手教你Android手机与BLE终端通信--连接,发送和接收数据

    假设你还没有看上一篇 手把手教你Android手机与BLE终端通信--搜索,你就先看看吧,由于这一篇要接着讲搜索到蓝牙后的连接.和连接后的发送和接收数据. 评论里有非常多人问假设一条信息特别长,怎么不 ...

  7. TCP程序中发送和接收数据

    这里我们来探讨一下在网络编程过程中,有关read/write 或者send/recv的使用细节.这里有关常用的阻塞/非阻塞的解释在网上有很多很好的例子,这里就不说了,还有errno ==EAGAIN ...

  8. java-TCP协议发送和接收数据

    TCP协议接收数据的步骤: A:创建接收数据的Socket对象 创建对象的时候要指定端口 B:监听客户端连接 等待客户端连接 C:获取Socket对象的输入流(字节流) D:读数据,并显示在控制台 E ...

  9. MPTCP 源码分析(四) 发送和接收数据

    简述:      MPTCP在发送数据方面和TCP的区别是可以从多条路径中选择一条 路径来发送数据.MPTCP在接收数据方面与TCP的区别是子路径对无序包 进行重排后,MPTCP的mpcb需要多所有子 ...

随机推荐

  1. zoo.cfg配置

    zookeeper的默认配置文件为zookeeper/conf/zoo_sample.cfg,需要将其修改为zoo.cfg.其中各配置项的含义,解释如下: 1.tickTime:CS通信心跳时间 Zo ...

  2. Sqlite数据库 找不到请求的 .Net Framework Data Provider。可能没有安装

      解决方法 在web.config里面添加 <system.data> <DbProviderFactories> <remove invariant="Sy ...

  3. 深入学习Heritrix---解析处理器(Processor)(转)

    深入学习Heritrix---解析处理器(Processor) 本节解析与处理器有关的内容. 与处理器有关的主要在以下几个类:Processor(处理器类),ProcessorChain(处理器类), ...

  4. nginx中针对目录进行IP限制

    一个不错的nginx中针对目录进行IP限制 ,这里我以phpmyadmin目录只能让内网IP访问,而外网不能访问的配置方法,有需要的同学可参考. nginx phpmyadmin 针对内网ip用户开放 ...

  5. Yii入门教程

    1准备Yii源码 首先新建helloyii目录作为Web应用的根目录,并添加到Nginx的配置文件中.然后将Yii框架源码部署到helloyii下,目录结构如下: helloyii/ |-- fram ...

  6. 细雨学习笔记:JMeter 的主要测试组件总结

    1. 测试计划是使用 JMeter 进行测试的起点,它是其它 JMeter 测试元件的容器. 2. 线程组代表一定数量的并发用户,它可以用来模拟并发用户发送请求.实际的请求内容在Sampler中定义, ...

  7. Yii笔记---redirect重定向

    Yii的redirect方法在CControler与CHttpRequest之中都有被定义,CController中的redirect调用了CHttpRequest中的redirect方法.我们平常调 ...

  8. 《深入理解C#》第3版 学习进度备忘

    学习资源:<深入理解C#>第3版 知识基础支持: <C# in a nutshell> O Reilly出版社,是一本从头介绍C#的优秀图书.<Essential C#5 ...

  9. 150个JS特效脚本

    收集了其它一些不太方便归类的JS特效,共150个,供君查阅. 1. simplyScroll simplyScroll这个jQuery插件能够让任意一组元素产生滚动动画效果,可以是自动.手动滚动,水平 ...

  10. BITED-Windows8应用开发学习札记之四:如何在Win8 应用中实现语义缩放

    语意缩放的意义在于:创新的语意缩放外观,让你的应用随时展现信息可视化的力量.如图表般的Tile,随着数据的不同而变化,让你的页面更富节奏.而所谓的语意缩放就是通过上下文的跳转,帮助我们实现一种更快更便 ...