Python TCP'发送'套接字缓冲区大小

时间:2018-02-09 15:33:10

标签: python sockets tcp

我想使用TCP Python socket模块发送/接收'已分配的'数据。 我的接收服务器端socket设置为在单个recv呼叫中接收40个字节的数据:

while True:
    data = connection.recv(40)
    if not data:
        break
    ...
connection.close()

我有一些〜500字节长的样本数据,转换为bytes对象,由'客户'发送到'服务器':

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
...
s.send(sample_data)

虽然我只有一次调用send方法,但这意味着客户端一次发送40个字节的'sample_data',而服务器'一次请求'40个字节,只要整个包没有完全发送?

我在this post中找到SO_SNDBUF参数设置send socket缓冲区的大小,但它与'普通'socket有何不同之处SO_SNDBUF正在设定?

buffer_size = 40
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.setsockopt(socket.SOL_SOCKET, socket.SO_SNDBUF, buffer_size)
...
s.send(sample_data)

1 个答案:

答案 0 :(得分:2)

TCP是一种流协议,意味着没有消息边界。它只是一个字节流。把它想象成一个FIFO。如果客户端发送500个字节,那么在服务器上将接收500个总字节。 recv(40)将按发送顺序从1-40个字节收到。您必须检查返回值以查看您收到了多少。

您可以收到数据长度:40,40,40,40,40,40,40,40,40,40,40,40,20

或者你可以得到类似的东西:40,40,5,40,40,40,40,40,40,40,40,40,40,15

在阻塞套接字上创建另一个recv将挂起,直到收到至少一个字节,或者如果客户端关闭套接字则返回零字节。

由服务器将数据连接在一起并确定是否接收到完整的数据传输。通常,您需要定义协议以确定完整消息的含义。这可能是&#34; 500字节是一个完整的消息&#34;。您还需要处理发送两条消息并且单个 <asp:SqlDataSource ID="SqlDataSource1" runat="server" ConnectionString='<%$ ConnectionStrings:ShiftScheduleConnectionString %>' DeleteCommand="DELETE FROM [Example] WHERE [ID] = @ID" InsertCommand="INSERT INTO [Example] ([AssociateName], [Login], [Logout], [Home_Login], [Home_Logout]) VALUES (@AssociateName, @Login, @Logout, @Home_Login, @Home_Logout)" SelectCommand="SELECT * FROM [Example]" UpdateCommand="UPDATE [Example] SET [AssociateName] = @AssociateName, [Login] = @Login, [Logout] = @Logout, [Home_Login] = @Home_Login, [Home_Logout] = @Home_Logout WHERE [ID] = @ID"> <DeleteParameters> <asp:Parameter Name="ID" Type="Int32"></asp:Parameter> </DeleteParameters> <InsertParameters> <asp:Parameter Name="AssociateName" Type="String"></asp:Parameter> <asp:Parameter Name="Login" Type="String"></asp:Parameter> <asp:Parameter Name="Logout" Type="String"></asp:Parameter> <asp:Parameter Name="Home_Login" Type="String"></asp:Parameter> <asp:Parameter Name="Home_Logout" Type="String"></asp:Parameter> </InsertParameters> <UpdateParameters> <asp:Parameter Name="AssociateName" Type="String"></asp:Parameter> <asp:Parameter Name="Login" Type="String"></asp:Parameter> <asp:Parameter Name="Logout" Type="String"></asp:Parameter> <asp:Parameter Name="Home_Login" Type="String"></asp:Parameter> <asp:Parameter Name="Home_Logout" Type="String"></asp:Parameter> <asp:Parameter Name="ID" Type="Int32"></asp:Parameter> </UpdateParameters> </asp:SqlDataSource> <asp:GridView ID="GridView1" OnRowUpdating="GridView1_RowUpdating" OnRowDataBound="GridView1_RowDataBound" OnRowEditing="GridView1_RowEditing" runat="server" AutoGenerateColumns="False" DataKeyNames="ID" DataSourceID="SqlDataSource1"> <Columns> <asp:CommandField ShowEditButton="True"></asp:CommandField> <asp:BoundField DataField="ID" HeaderText="ID" ReadOnly="True" InsertVisible="False" SortExpression="ID"></asp:BoundField> <asp:BoundField DataField="AssociateName" HeaderText="AssociateName" SortExpression="AssociateName"></asp:BoundField> <asp:BoundField DataField="Login" HeaderText="Login" SortExpression="Login"></asp:BoundField> <asp:BoundField DataField="Logout" HeaderText="Logout" SortExpression="Logout"></asp:BoundField> <asp:BoundField DataField="Home_Login" HeaderText="Home_Login" SortExpression="Home_Login"></asp:BoundField> <asp:BoundField DataField="Home_Logout" HeaderText="Home_Logout" SortExpression="Home_Logout"></asp:BoundField> </Columns> </asp:GridView> 可以从一条消息的结尾和另一条消息的开头获取数据的情况。

通常不需要使用套接字选项调整缓冲区大小。