当前位置:   article > 正文

windows网络编程实验4采用C++进行TCP通信之多线程文件传输

windows网络编程实验4采用C++进行TCP通信之多线程文件传输

实验要求:使服务器与多个客户端进行通信,同时接收多个客户端上传的文件。

服务端代码:

  1. #include"iostream"
  2. #include"afxmt.h"
  3. #include"process.h"
  4. #include"winsock2.h"
  5. #include"fstream"
  6. #include"WS2tcpip.h"
  7. #include"direct.h"
  8. #define PORT 65432
  9. #pragma comment(lib,"ws2_32.lib")
  10. using namespace std;
  11. struct fileMessage
  12. {
  13. char fileName[256];
  14. long int fileSize;
  15. };
  16. /*主程序和线程函数共用的全局变量定义*/
  17. char fname[128] = { 0 }; //发送给客户端的无路径信息的文件名
  18. ifstream inFile; //定义文件的输入流
  19. CMutex Section; //创建互斥对象
  20. void rdFile(void* par); //发送文件的线程函数声明
  21. /*主函数*/
  22. int main()
  23. {
  24. SOCKET sock_server; //定义监听套接字
  25. struct sockaddr_in addr;
  26. struct sockaddr_in client_addr; //存放本地地址和客户地址的变量
  27. SOCKET newsock; //储存accept()返回的套接字描述符
  28. /*初始化winsock DLL*/
  29. WSADATA wsaData;
  30. if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
  31. {
  32. cout << "加载winSock动态链接库失败!\n";
  33. return 0;
  34. }
  35. /*创建监听套接字*/
  36. if ((sock_server = socket(AF_INET, SOCK_STREAM, 0)) < 0)
  37. {
  38. cout << "创建套接字失败!\n";
  39. WSACleanup();
  40. return 0;
  41. }
  42. /*绑定IP地址与端口*/
  43. memset((void*)&addr, 0, sizeof(addr));
  44. addr.sin_family = AF_INET;
  45. addr.sin_port = htons(65432);
  46. addr.sin_addr.s_addr = htonl(INADDR_ANY);
  47. if (bind(sock_server, (struct sockaddr*)&addr, sizeof(addr)) != 0)
  48. {
  49. cout << "绑定失败!\n";
  50. closesocket(sock_server);
  51. WSACleanup();
  52. return 0;
  53. }
  54. if (listen(sock_server, 5) != 0)
  55. {
  56. cout << "listen函数调用失败!\n";
  57. closesocket(sock_server);
  58. WSACleanup();
  59. return 0;
  60. }
  61. else
  62. {
  63. cout << "listenning.....\n";
  64. }
  65. /*接收客户连接请求*/
  66. int addr_len = sizeof(struct sockaddr_in);
  67. while (true)
  68. {
  69. newsock = accept(sock_server, (LPSOCKADDR)&client_addr, &addr_len);
  70. if (newsock != INVALID_SOCKET)
  71. {
  72. cout << "一个客户连接成功!" << endl;
  73. _beginthread(rdFile, 0, (LPVOID)newsock);
  74. }
  75. else
  76. {
  77. break;
  78. }
  79. }
  80. closesocket(newsock);
  81. closesocket(sock_server);
  82. WSACleanup();
  83. return 0;
  84. }
  85. void rdFile(void* par)
  86. {
  87. /*定义文件传输所需变量*/
  88. struct fileMessage fileMsg;
  89. SOCKET sock = (SOCKET)par;
  90. long int filelen;
  91. char filename[500] = "C:\\Users\\86152\\source\\repos\\textfile"; //指定文件的保存目录
  92. char ok[3] = "OK";
  93. char fileBuffer[1000]; //接收文件数据的缓冲区
  94. _mkdir(filename); //_mkdir()用于创建文件夹,其声明包含在direct.h中
  95. /*接收文件名及文件长度信息*/
  96. if ((filelen = recv(sock, (char*)&fileMsg, sizeof(fileMsg), 0)) <= 0)
  97. {
  98. cout << "未接收到文件名及文件长度!\n";
  99. closesocket(sock);
  100. WSACleanup();
  101. return;
  102. }
  103. filelen = ntohl(fileMsg.fileSize);
  104. strcat_s(filename, fileMsg.fileName);
  105. ofstream outFile(filename, ios::out | ios::binary); //创建文件对象
  106. if (!outFile.is_open())
  107. {
  108. cout << "Cannot open" << filename << endl;
  109. closesocket(sock);
  110. WSACleanup();
  111. return; //文件打开失败则退出
  112. }
  113. send(sock, ok, sizeof(ok), 0); //发送接收文件数据的确认信息
  114. int size = 0;
  115. do
  116. {
  117. size = recv(sock, fileBuffer, sizeof(fileBuffer), 0);
  118. if (size <= 0)break;
  119. outFile.write(fileBuffer, size);
  120. filelen -= size;
  121. } while (filelen > 0);
  122. if (filelen == 0)
  123. {
  124. cout << "Transfer finished!\n";
  125. }
  126. else
  127. {
  128. cout << "Transfer Failed!\n";
  129. }
  130. outFile.close();
  131. closesocket(sock);
  132. }

客户端代码:

  1. #include<iostream>
  2. #include"fstream"
  3. #include"winsock2.h"
  4. #include"WS2tcpip.h"
  5. #include"direct.h"
  6. #pragma comment(lib,"ws2_32.lib")
  7. using namespace std;
  8. struct fileMessage //定义存储文件信息的结构体
  9. {
  10. char fileName[256];
  11. long int fileSize;
  12. };
  13. int main()
  14. {
  15. /*定义网络连接的相关变量*/
  16. int sock_client; //定义套接字
  17. struct sockaddr_in server_addr; //用于存放服务器地址的变量
  18. int addr_len = sizeof(struct sockaddr_in); //地址长度
  19. /*初始化winsock DLL*/
  20. WSADATA wsaData;
  21. if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
  22. {
  23. cout << "加载winsock动态链接库失败!\n";
  24. return 0;
  25. }
  26. char filename[500]; //用于存储要传输的文件的文件路径
  27. cout << "输入要输入的文件路径:";
  28. cin.getline(filename, 500);
  29. /*创建套接字*/
  30. if ((sock_client = socket(AF_INET, SOCK_STREAM, 0)) < 0)
  31. {
  32. cout << "创建套接字失败!\n";
  33. WSACleanup();
  34. return 0;
  35. }
  36. /*输入服务器IP地址及端口号*/
  37. char IP[20];
  38. // unsigned short port;
  39. in_addr a;
  40. cout << "请输入服务器IP地址:";
  41. cin >> IP;
  42. inet_pton(AF_INET, IP, &a);
  43. memset((void*)&server_addr, 0, addr_len);
  44. server_addr.sin_family = AF_INET;
  45. server_addr.sin_port = htons(65432);
  46. server_addr.sin_addr.s_addr = a.S_un.S_addr;
  47. if (connect(sock_client, (struct sockaddr*)&server_addr, addr_len) != 0)
  48. {
  49. cout << "连接失败!\n";
  50. closesocket(sock_client);
  51. WSACleanup();
  52. return 0;
  53. }
  54. char OK[3], fileBuffer[1000]; //定义接收“OK”的缓冲区和发送缓冲区
  55. struct fileMessage fileMsg; //定义保存文件名及文件长度的结构变量
  56. ifstream inFile(filename, ios::in | ios::binary); //定义文件对象并打开文件
  57. if (!inFile.is_open())
  58. {
  59. cout << "CAnnot open" << filename << endl;
  60. closesocket(sock_client);
  61. WSACleanup();
  62. return 0; //文件打开失败则退出
  63. }
  64. /*从文件路径中提取文件名保存到结构变量fileMsg中*/
  65. unsigned int size = strlen(filename);
  66. while (filename[size] != '\\' && size > 0)size--;
  67. strcpy_s(fileMsg.fileName, filename + size);
  68. /*获取文件长度并存入结构变量fileMsg中*/
  69. inFile.seekg(0, ios::end); //将文件的位置指针移到文件末尾
  70. size = inFile.tellg(); //获取当前文件位置指针值
  71. fileMsg.fileSize = htonl(size); //将文件长度存入结构变量fileMeg
  72. send(sock_client, (char*)&fileMsg, sizeof(fileMsg), 0);//发送fileMeg
  73. if (recv(sock_client, OK, sizeof(OK), 0) <= 0) //接收对方发来的OK信息
  74. {
  75. cout << "接收OK失败,程序退出!\n";
  76. closesocket(sock_client);
  77. WSACleanup();
  78. return 0;
  79. }
  80. if (strcmp(OK, "OK") == 0) //如果对方已准备好接收则发送文件内容
  81. {
  82. inFile.seekg(0, ios::beg); //将文件的位置指针返回到文件头
  83. while (!inFile.eof())
  84. {
  85. inFile.read(fileBuffer, sizeof(fileBuffer));
  86. size = inFile.gcount(); //读取实际读取的字节数
  87. send(sock_client, fileBuffer, size, 0);
  88. }
  89. cout << "File Transfer Finished!\n";
  90. inFile.close(); //关闭文件
  91. }
  92. else
  93. {
  94. cout << "对方无法接收文件!";
  95. }
  96. closesocket(sock_client);
  97. WSACleanup();
  98. return 0;
  99. }

实现效果:

 

实验要求:服务器同时向多个客户端发送文件

  1. #include<iostream>
  2. #include"fstream"
  3. #include"winsock2.h"
  4. #pragma comment(lib,"ws2_32.lib")
  5. using namespace std;
  6. struct fileMessage //定义存储文件信息的结构体
  7. {
  8. char fileName[256];
  9. long int fileSize;
  10. };
  11. int main()
  12. {
  13. SOCKET sock_server; //定义监听套接字
  14. struct sockaddr_in addr;
  15. struct sockaddr_in client_addr; //存放本地地址和客户地址的变量
  16. SOCKET newsock; //储存accept()返回的套接字描述符
  17. /*初始化winsock DLL*/
  18. WSADATA wsaData;
  19. if (WSAStartup(MAKEWORD(2,2),&wsaData)!=0)
  20. {
  21. cout << "加载winSock动态链接库失败!\n";
  22. return 0;
  23. }
  24. char filename[500]; //用于存储要传输的文件的文件路径
  25. cout << "输入要输入的文件路径:";
  26. cin.getline(filename, 500);
  27. /*创建监听套接字*/
  28. if ((sock_server=socket(AF_INET,SOCK_STREAM,0))<0)
  29. {
  30. cout << "创建套接字失败!\n";
  31. WSACleanup();
  32. return 0;
  33. }
  34. /*绑定IP地址与端口*/
  35. memset((void*)&addr, 0, sizeof(addr));
  36. addr.sin_family = AF_INET;
  37. addr.sin_port = htons(65432);
  38. addr.sin_addr.s_addr = htonl(INADDR_ANY);
  39. if (bind(sock_server,(struct sockaddr*)&addr,sizeof(addr))!=0)
  40. {
  41. cout << "绑定失败!\n";
  42. closesocket(sock_server);
  43. WSACleanup();
  44. return 0;
  45. }
  46. if (listen(sock_server,5)!=0)
  47. {
  48. cout << "listen函数调用失败!\n";
  49. closesocket(sock_server);
  50. WSACleanup();
  51. return 0;
  52. }
  53. else
  54. {
  55. cout << "listenning.....\n";
  56. }
  57. /*接收客户连接请求*/
  58. int addr_len = sizeof(struct sockaddr_in);
  59. if ((newsock=accept(sock_server,(struct sockaddr*)&client_addr,&addr_len))==INVALID_SOCKET)
  60. {
  61. cout << "accept函数调用失败!\n";
  62. closesocket(sock_server);
  63. WSACleanup();
  64. return 0;
  65. }
  66. cout << "客户连接成功!" << endl;
  67. char OK[3], fileBuffer[1000]; //定义接收“OK”的缓冲区和发送缓冲区
  68. struct fileMessage fileMsg; //定义保存文件名及文件长度的结构变量
  69. ifstream inFile(filename, ios::in | ios::binary); //定义文件对象并打开文件
  70. if (!inFile.is_open())
  71. {
  72. cout << "CAnnot open" << filename << endl;
  73. closesocket(newsock);
  74. closesocket(sock_server);
  75. WSACleanup();
  76. return 0; //文件打开失败则退出
  77. }
  78. /*从文件路径中提取文件名保存到结构变量fileMsg中*/
  79. unsigned int size = strlen(filename);
  80. while (filename[size] !='\\' && size> 0)size--;
  81. strcpy_s(fileMsg.fileName, filename + size);
  82. /*获取文件长度并存入结构变量fileMsg中*/
  83. inFile.seekg(0, ios::end); //将文件的位置指针移到文件末尾
  84. size = inFile.tellg(); //获取当前文件位置指针值
  85. fileMsg.fileSize = htonl(size); //将文件长度存入结构变量fileMeg
  86. send(newsock, (char*)&fileMsg, sizeof(fileMsg), 0);//发送fileMeg
  87. if (recv(newsock,OK,sizeof(OK),0)<=0) //接收对方发来的OK信息
  88. {
  89. cout << "接收OK失败,程序退出!\n";
  90. closesocket(newsock);
  91. closesocket(sock_server);
  92. WSACleanup();
  93. return 0;
  94. }
  95. if (strcmp(OK,"OK")==0) //如果对方已准备好接收则发送文件内容
  96. {
  97. inFile.seekg(0, ios::beg); //将文件的位置指针返回到文件头
  98. while (!inFile.eof())
  99. {
  100. inFile.read(fileBuffer, sizeof(fileBuffer));
  101. size = inFile.gcount(); //读取实际读取的字节数
  102. send(newsock, fileBuffer, size, 0);
  103. }
  104. cout << "File Transfer Finished!\n";
  105. inFile.close(); //关闭文件
  106. }
  107. else
  108. {
  109. cout << "对方无法接收文件!";
  110. }
  111. closesocket(newsock);
  112. closesocket(sock_server);
  113. WSACleanup();
  114. return 0;
  115. }

 客户端代码:

  1. #include<iostream>
  2. #include"fstream"
  3. #include"winsock2.h"
  4. #include"WS2tcpip.h"
  5. #include"direct.h"
  6. #pragma comment(lib,"ws2_32.lib")
  7. using namespace std;
  8. struct fileMessage
  9. {
  10. char fileName[256];
  11. long int fileSize;
  12. };
  13. int main()
  14. {
  15. /*定义网络连接的相关变量*/
  16. int sock_client; //定义套接字
  17. struct sockaddr_in server_addr; //用于存放服务器地址的变量
  18. int addr_len = sizeof(struct sockaddr_in); //地址长度
  19. /*初始化winsock DLL*/
  20. WSADATA wsaData;
  21. if (WSAStartup(MAKEWORD(2,2),&wsaData)!=0)
  22. {
  23. cout << "加载winsock动态链接库失败!\n";
  24. return 0;
  25. }
  26. /*创建套接字*/
  27. if ((sock_client=socket(AF_INET,SOCK_STREAM,0))<0)
  28. {
  29. cout << "创建套接字失败!\n";
  30. WSACleanup();
  31. return 0;
  32. }
  33. /*输入服务器IP地址及端口号*/
  34. char IP[20];
  35. // unsigned short port;
  36. in_addr a;
  37. cout << "请输入服务器IP地址:";
  38. cin >> IP;
  39. inet_pton(AF_INET, IP, &a);
  40. memset((void*)&server_addr, 0, addr_len);
  41. server_addr.sin_family = AF_INET;
  42. server_addr.sin_port = htons(65432);
  43. server_addr.sin_addr.s_addr = a.S_un.S_addr;
  44. if (connect(sock_client, (struct sockaddr*)&server_addr, addr_len) != 0)
  45. {
  46. cout << "连接失败!\n";
  47. closesocket(sock_client);
  48. WSACleanup();
  49. return 0;
  50. }
  51. /*定义文件传输所需变量*/
  52. struct fileMessage fileMsg;
  53. long int filelen;
  54. char filename[500] = "D:\\BaiduNetdiskDownload\\visualstudio\\vsfile\\transferfileclient"; //指定文件的保存目录
  55. char ok[3] = "OK";
  56. char fileBuffer[1000]; //接收文件数据的缓冲区
  57. _mkdir(filename); //_mkdir()用于创建文件夹,其声明包含在direct.h中
  58. /*接收文件名及文件长度信息*/
  59. if ((filelen=recv(sock_client,(char*)&fileMsg,sizeof(fileMsg),0))<=0)
  60. {
  61. cout << "未接收到文件名及文件长度!\n";
  62. closesocket(sock_client);
  63. WSACleanup();
  64. return 0;
  65. }
  66. filelen = ntohl(fileMsg.fileSize);
  67. strcat_s(filename, fileMsg.fileName);
  68. ofstream outFile(filename, ios::out | ios::binary); //创建文件对象
  69. if (!outFile.is_open())
  70. {
  71. cout << "Cannot open" << filename << endl;
  72. closesocket(sock_client);
  73. WSACleanup();
  74. return 0; //文件打开失败则退出
  75. }
  76. send(sock_client, ok, sizeof(ok), 0); //发送接收文件数据的确认信息
  77. int size = 0;
  78. do
  79. {
  80. size = recv(sock_client, fileBuffer, sizeof(fileBuffer), 0);
  81. if (size <= 0)break;
  82. outFile.write(fileBuffer, size);
  83. filelen -= size;
  84. } while (filelen>0);
  85. if (filelen==0)
  86. {
  87. cout << "Transfer finished!\n";
  88. }
  89. else
  90. {
  91. cout << "Transfer Failed!\n";
  92. }
  93. outFile.close();
  94. closesocket(sock_client);
  95. WSACleanup();
  96. return 0;
  97. }

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/我家自动化/article/detail/172151?site
推荐阅读
相关标签
  

闽ICP备14008679号