[关闭]
@1405010304geshuaishuai 2016-10-18T03:45:40.000000Z 字数 4440 阅读 999

作业三 实验报告

网络通信 文件传输


实验一

1-1 实验题目

服务器端和客户端各传递1次字符串。考虑到使用TCP协议,所以传递字符串前先以4字节整数型方式传递字符串长度。连接时服务器端和客户端数据传输格式如下:
格式
        图1-1 传输数据格式

1-2 实验思路

从题目中可以看出首先将用户输入到文本框中的数据进行解析,看看到底有多少个字符,然后在将字符数据和后面的信息一起发过去,在题目中,我们很容易看到一共是四个字节来记录文本的数据,所以我们默认将这四个数据全都设为0,然后经过对用户输入的信息分析之后在修改相应的位数。

1-2 实现过程

界面设计如下:
界面1
         图1-2 客户端界面
界面2
         图1-3 服务器端界面
当用户在信息输入框中输入字符,点击发送,服务器端就会返还回字符的个数加数据。
客户端核心代码如下:

  1. void tcp_client1::datatranslate()
  2. {
  3. QTextCodec *code=QTextCodec::codecForName("GBK");
  4. QString message=ui->lineEdit_meseg->text();
  5. int a=0, b=0, c=0, d=0;
  6. if(message.length()<10)
  7. {
  8. d=message.length();
  9. }
  10. else if(message.length()<100)
  11. {
  12. d=message.length()%10;
  13. c=message.length()/10;
  14. }
  15. else if(message.length()<1000)
  16. {
  17. d=message.length()%10;
  18. c=message.length()%100/10;
  19. b=message.length()/100;
  20. }
  21. else if(message.length()<10000)
  22. {
  23. d=message.length()%10;
  24. c=message.length()%100/10;
  25. b=message.length()%1000/100;
  26. a=message.length()/1000;
  27. }
  28. QString qa= QString::number(a);
  29. QString qb= QString::number(b);
  30. QString qc= QString::number(c);
  31. QString qd= QString::number(d);
  32. QByteArray sa=code->fromUnicode(qa);
  33. QByteArray sb=code->fromUnicode(qb);
  34. QByteArray sc=code->fromUnicode(qc);
  35. QByteArray sd=code->fromUnicode(qd);
  36. QByteArray mes1=code->fromUnicode(message);
  37. this->tcpSocket->write(sa+sb+sc+sd+mes1);
  38. ui->lineEdit_meseg->clear();
  39. }

服务器端核心代码如下:

  1. void tcp_server1::readdata()
  2. {
  3. QString fromClient = tcpSocket->readAll();
  4. QTextCodec *code=QTextCodec::codecForName("GBK");
  5. QByteArray mes=code->fromUnicode(fromClient);
  6. ui->char_num->setText(mes);
  7. tcpSocket->write(mes);
  8. }

1-3 运行效果图

运行
           图1-4 运行效果图
1-4 实验总结
通过本次实验,对TCP通信有了进一步的认识,将字符的个数发送到服务器这里首先在客户端进行数据的解析,通过计算算出一共有多少字符,然后一起和数据进行发送,当服务器接收到数据时,原封不动的将数据返回给客户端,就像前面做过的迭代服务器一样。


实验二

2-1 实验题目

创建收发文件的服务器端/客户端,实现顺序如下。
客户端接收用户输入的传输文件名。
客户端请求服务器端传输该文件名所指文件。
如果指定文件存在,服务器端就将其发送给客户端;反之,则断开连接。

2-2 实验思路

考虑到本题目涉及到文件的传输,所以只实现了其中由客户端选择文件上传到服务端,由于水平有限,所以只能是先到这一步。首先客户端的界面如下:
界面
         图2-1 客户端运行界面

服务端的界面如下:
界面
         图2-2 服务器端运行界面
首先客户端打开文件,服务端选择监听,然后哭护短选择上传文件,服务端开始接收文件,知道完成传输。

2-3 设计过程

实现文件的传输,在实际的文件传输以前,需要将整个传输数据的大小、文件名的大小还有文件名等信息放在数据的开头进行传输,这里可以把他们统称为文件头结构。数据是分为数据块进行发送的,每次发送的数据块的大小为指定大小,每当有数据发送时就更新进度条,如果数据发送完毕,便关闭本地文件和客户端套接字。服务器端先分别接收了数据总大小、文件名大小及文件名等文件头结构的信息,然后才接受实际的文件。一旦建立连接,客户端套接字便发射connected()信号,从而调用startTransfer()来发送头文件结构。这时服务器端发现有数据到来便更新进度条,在其中获取发送过来的数据。而在客户端,当有数据发送时,也会更新进度条,在其中将后面的数据库发送出去。
客户端核心代码:

  1. void Client::startTransfer()
  2. {
  3. localFile=new QFile(fileName);
  4. if(!localFile->open(QFile::ReadOnly)){
  5. qDebug()<<"client: open file error!";
  6. return;
  7. }
  8. totalBytes=localFile->size();
  9. QDataStream sendOut(&outBlock, QIODevice::WriteOnly);
  10. sendOut.setVersion(QDataStream::Qt_4_0);
  11. QString currentFileName=fileName.right(fileName.size()-fileName.lastIndexOf('/')-1);
  12. sendOut<<qint64(0)<<qint64(0)<<currentFileName;
  13. totalBytes+=outBlock.size();
  14. sendOut.device()->seek(0);
  15. sendOut<<totalBytes<<qint64((outBlock.size()-sizeof(qint64)*2));
  16. bytesToWrite=totalBytes-tcpClient->write(outBlock);
  17. ui->clientStatusLabel->setText(tr("已连接"));
  18. outBlock.resize(0);
  19. }
  1. void Client::updateClientProcess(qint64 numBytes)
  2. {
  3. bytesWritten+=(int)numBytes;
  4. if(bytesToWrite>0){
  5. outBlock=localFile->read(qMin(bytesToWrite, payloadSize));
  6. bytesToWrite-=(int)tcpClient->write(outBlock);
  7. outBlock.resize(0);
  8. }else{
  9. localFile->close();
  10. }
  11. ui->clientProgressBar->setMaximum(totalBytes);
  12. ui->clientProgressBar->setValue(bytesWritten);
  13. if(bytesWritten==totalBytes){
  14. ui->clientStatusLabel->setText(tr("传送文件 %1 成功").arg(fileName));
  15. localFile->close();
  16. tcpClient->close();
  17. }
  18. }

服务器端代码:

  1. void Server::updateServerProgress()
  2. {
  3. QDataStream in(tcpServerConnection);
  4. in.setVersion(QDataStream::Qt_4_0);
  5. if(bytesReceived<=sizeof(qint64)*2){
  6. if((tcpServerConnection->bytesAvailable()>=sizeof(qint64)*2)&&(fileNameSize==0)){
  7. in>>totalBytes>>fileNameSize;
  8. bytesReceived+=sizeof(qint64)*2;
  9. }
  10. if((tcpServerConnection->bytesAvailable()>=fileNameSize)&&(fileNameSize!=0)){
  11. in>>fileName;
  12. ui->serverStatusLabel->setText(tr("接收文件 %1 ...").arg(fileName));
  13. bytesReceived+=fileNameSize;
  14. //QString dir="D:\\server\\";
  15. /*QDir d;
  16. d.mkpath(dir);*/
  17. localFile=new QFile(dir+"\\"+fileName);
  18. if(! localFile->open(QFile::WriteOnly)){
  19. qDebug()<<"server: open file error!";
  20. return;
  21. }
  22. }else{
  23. return;
  24. }
  25. }
  26. if(bytesReceived<totalBytes){
  27. bytesReceived+=tcpServerConnection->bytesAvailable();
  28. inBlock=tcpServerConnection->readAll();
  29. localFile->write(inBlock);
  30. inBlock.resize(0);
  31. }
  32. ui->serverProgressBar->setMaximum(totalBytes);
  33. ui->serverProgressBar->setValue(bytesReceived);
  34. if(bytesReceived==totalBytes){
  35. tcpServerConnection->close();
  36. ui->startButton->setEnabled(true);
  37. ui->serverStatusLabel->setText(tr("接收文件 %1 成功!").arg(fileName));
  38. }
  39. }

2-4 实验总结

通过本次实验,了解到文件在客户端与服务器端的传输,相信文件能从客户端上传到服务端,当然也能从服务端下载到客户端,方法是一样的,首先在客户端输入要在服务器端下载的文件名称,发送到服务器,服务器接收到名称然后去指定的文件夹下去查找,如果有则将这个文件传送到客户端,如果没有则断开连接。

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注