概述
利用tcp协议进行简单的c/s模式的文件传输。
利用了流式套接字实现服务器和客户端之间的文件传输
要求:
服务器端和客户端是控制台应用程序
服务器端启动后从键盘输入要发送文件存放的位置和文件名
客户端启动之后输入服务器的ip地址,与服务器建立连接
建立连接后下载服务器提供的文件,并保存到本地
服务器:
#include "pch.h"
#include <iostream>
#include"fstream"
#include"winsock2.h"
#pragma comment(lib,"ws2_32.lib")
using namespace std;
struct filel { //定义储存文件信息的结构体
char fileName[255]; //文件名
long int filesize; //文件大小
};
int main()
{
SOCKET sock_server,newsock;
struct sockaddr_in addr, addr_client;
WSADATA wsaData;
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) {
cout << "加载动态连接库失败!" << endl;
return 0;
}
char filePath[500]; //用于存放要传输的文件的传输路径
cout << "文件路径:" << endl;
cin.getline(filePath, 500);
if ((sock_server = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
cout << "套接字创建失败!" << endl;
WSACleanup();
return 0;
}
int addr_len = sizeof(struct sockaddr_in);
memset((void*)&addr, 0, addr_len);
addr.sin_family = AF_INET;
addr.sin_port = htons(60000);
addr.sin_addr.s_addr = htonl(INADDR_ANY);
if (bind(sock_server, (struct sockaddr *)&addr, sizeof(addr)) != 0) {
cout << "地址绑定失败!" << endl;
closesocket(sock_server);
WSACleanup();
return 0;
}
if (listen(sock_server, 0) != 0) {
cout << "监听套接字调用失败!" << endl;
closesocket(sock_server);
WSACleanup();
return 0;
}
else
cout << "listen......" << endl;
if ((newsock = accept(sock_server, (struct sockaddr*)&addr_client, &addr_len)) == INVALID_SOCKET) {
cout << "接收客户端连接失败!" << endl;
closesocket(sock_server);
WSACleanup();
return 0;
}
cout << "连接成功!" << endl;
char rec[3], buffer[1000]; //定义接收确认消息的缓冲区和发送缓冲区
struct filel file; //定义保存文件名和文件长度的结构体变量
ifstream inFile(filePath, ios::in | ios::binary);//定义文件对象并打开文件
if (!inFile.is_open()) {
cout << "文件打开失败!" << filePath << endl;
closesocket(sock_server);//文件打开失败就退出户
WSACleanup();
return 0;
}
unsigned int size = strlen(filePath);
while (filePath[size] != '\'&&size > 0)size--;
strcpy_s(file.fileName, filePath + size);
inFile.seekg(0, ios::end); //将文件位置指针移到文件末尾
size = inFile.tellg(); //获取当前文件的位置指针,即为文件长度
file.filesize = htonl(size); //将文件长度存入filesize里
send(newsock, (char*)&file, sizeof(file), 0);
if (recv(newsock, rec, sizeof(rec), 0) <= 0) {
cout << "接收确认信息失败!" << endl;
closesocket(sock_server);
closesocket(newsock);
WSACleanup();
return 0;
}
if (strcmp(rec, "ok") == 0) {
inFile.seekg(0, ios::beg); //将文件位置指针返回到头文件
while (!inFile.eof()) {
inFile.read(buffer, sizeof(buffer));
size = inFile.gcount(); //获取实际读取的字节数
send(newsock, buffer, size, 0);
}
cout << "文件传输结束!" << endl;
inFile.close();
}
else
cout << "无法接收文件!" << endl;
closesocket(sock_server);
closesocket(newsock);
WSACleanup();
return 0;
}
客户端:
#include "pch.h"
#include <iostream>
#include"fstream"
#include"winsock2.h"
#include"WS2tcpip.h"
#include"direct.h"
#pragma comment(lib,"ws2_32.lib")
using namespace std;
struct filel {
char fileName[255];
int fileSize;
};
int main() {
SOCKET sock_client;
struct sockaddr_in addr;
int addr_len = sizeof(struct sockaddr_in);
WSADATA wsaData;
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) {
cout << "加载动态连接库失败!" << endl;
return 0;
}
if ((sock_client = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
cout << "套接字创建失败!" << endl;
WSACleanup();
return 0;
}
char IP[20];
cout << "请输入服务器IP:" << endl;
cin >> IP;
in_addr a;
inet_pton(AF_INET, IP, &a);
memset((void*)&addr, 0, addr_len);
addr.sin_family = AF_INET;
addr.sin_port = htons(60000);
addr.sin_addr.s_addr = a.S_un.S_addr;
if (connect(sock_client, (struct sockaddr*)&addr, addr_len) != 0) {
cout << "连接失败!" << endl;
closesocket(sock_client);
WSACleanup();
return 0;
}
cout << "连接成功!" << endl;
// * * * 定义传输文件所需要的变量
struct filel file;
long int filelen;
char filePath[500]= "E:\";
char sen[3]="ok";
char buffer[1000]; //接收文件的数据缓冲区
_mkdir(filePath); //_mkdir()用于创建文件夹
if ((filelen = recv(sock_client, (char*)&file, sizeof(file), 0)) <= 0) {
cout << "未接收到文件名及文件长度!" << endl;
closesocket(sock_client);
WSACleanup();
return 0;
}
filelen = ntohl(file.fileSize);
strcat_s(filePath, file.fileName);
ofstream outFile(filePath, ios::out | ios::binary);
if (!outFile.is_open()) {
cout << "文件不能打开!" << filePath << endl;
closesocket(sock_client);
WSACleanup();
return 0;
}
send(sock_client, sen, sizeof(sen), 0);
int size = 0;
do {
size = recv(sock_client, buffer, sizeof(buffer), 0);
if (size <= 0)break;
outFile.write(buffer, size);
filelen -= size;
} while (filelen > 0);
if (filelen == 0) {
cout << "文件传输完毕!" << endl;
}
else
cout << "文件传输失败!" << endl;
outFile.close();
closesocket(sock_client);
WSACleanup();
return 0;
}
最后
以上就是悲凉奇迹为你收集整理的利用tcp实现简单的服务器/客户端文件传输的全部内容,希望文章能够帮你解决利用tcp实现简单的服务器/客户端文件传输所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复