socket编程向服务器发送文件,socket编程与大文件传输

本文介绍了基于TCP协议的客户端/服务器程序流程,包括连接建立、数据传输和断开连接的过程。在实际操作中,作者发现TCP协议不会自动拆分和合并大文件,需要在应用层处理。在发送大文件时,系统会自动拆分,但接收方需多次接收以获取完整文件。此外,文章提供了一个循环读取数据的函数示例。
摘要由CSDN通过智能技术生成

前段时间通过学习socket编程实现了客户端与服务器之间的大尺寸文件的传输,最近在参加一些笔试时,也遇到了socket的问题,遂整理出一些东西出来,和大家分享,也便于对这方面不了解的朋友迅速建立概念。

首先介绍一下基于TCP协议的客户端/服务器程序的一般流程:

a4c26d1e5885305701be709a3d33442f.png

服务器调用socket()、bind()、listen()完成初始化后,调用accept()阻塞等待,处于监听端口的状态,客户端调用socket()初始化后,调用connect()发出SYN段并阻塞等待服务器应答,服务器应答一个SYN+ACK段,客户端收到后从connect()返回,同时应答一个ACK段,服务器收到后从accept()返回。

数据传输的过程:

建立连接后,TCP协议提供全双工的通信服务,但是一般的客户端/服务器程序的流程是由客户端主动发起请求,服务器被动处理请求,一问一答的方式。因此,服务器从accept()返回后立刻调用read(),读socket就像读管道一样,如果没有数据到达就阻塞等待,这时客户端调用write()发送请求给服务器,服务器收到后从read()返回,对客户端的请求进行处理,在此期间客户端调用read()阻塞等待服务器的应答,服务器调用write()将处理结果发回给客户端,再次调用read()阻塞等待下一条请求,客户端收到后从read()返回,发送下一条请求,如此循环下去。

如果客户端没有更多的请求了,就调用close()关闭连接,就像写端关闭的管道一样,服务器的read()返回0,这样服务器就知道客户端关闭了连接,也调用close()关闭连接。注意,任何一方调用close()后,连接的两个传输方向都关闭,不能再发送数据了。如果一方调用shutdown()则连接处于半关闭状态,仍可接收对方发来的数据。

下图是典型的UDP客户端/服务器通讯过程,由于UDP较为简单,不再解释:

a4c26d1e5885305701be709a3d33442f.png

最后谈谈我在编程通过socket实现收发比较大的文件时遇到的问题。我本以为系统会自动为我拆分和合并报文,我可以直接在应用层发送和接受完整的文件。但实际测试结果告诉我,并不是这样。如果收发在一个主机上,一次只能接收最大65535字节的文件;如果不在同一主机,则只有1500字节。而发送可以将整个大文件直接送交文件描述符发送,无需自己分割,系统会自动分割;但接收时,需人为多次接收,才能把整个文件收完整。这一点请大家尤其要注意!下面提供给大家一个可以一直循环收到你所需要的数据的函数:

int read_data(int s, char *buf, int n)

{ int bcount;

int br;

bcount= 0;

br= 0;

while (bcount < n) {

if ((br= read(s,buf,n-bcount)) > 0) {

bcount += br;

buf += br;

}

else if (br < 0)

return(-1);

}

return(bcount);

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值