//对文件名传输进行处理
char filename[MAX_PATH];
int i = 0;
for (i = 0; i < len3; i++)
{
filename[i] = argv[3][i];
}
filename[i++] = ‘#‘;
//传输文件名
iResult = send(ConnectSocket, filename, strlen(filename), 0);
if (iResult == SOCKET_ERROR)
{
cout << "Send Filename : " << Sendbuffer << " with error " << WSAGetLastError() << "\n" << endl;
break;
}
//以二进制文件形式读取文件
ifstream sourcefile(argv[3], ios::in | ios::binary);
sourcefile.read(filebuf, MAX_LEN);
rec_file.write(Recvb, MAX_LEN);
//确定文件的大小
int len;
FILE* fp;
if(fp = fopen(argv[3], "r"))
{
fseek(fp, 0, SEEK_END);
printf("%ld\n", ftell(fp));
len = ftell(fp);
fclose(fp);
}
else
{
cout << "Error" << endl;
}
sourcefile.read(filebuf, MAX_LEN);
rec_file.write(Recvb, MAX_LEN);
while (left > 0)
{
if (left > MAX_LEN)
{
iResult = recvn(s, Recvb, MAX_LEN);
if (iResult == -1)
{
cout << "Receive failed with error " << WSAGetLastError() << endl;
return -1;
}
else if (iResult == 0)
{
cout << "Receive data stopped. There "<<left<<" bytes unreceived" << endl;
break;
}
else
{
cout << "Receive partial data : " << iResult << " bytes" << endl;
rec_file.write(Recvb, MAX_LEN);
left -= MAX_LEN;
}
}
else
{
iResult = recvn(s, Recvb, left);
if (iResult == -1)
{
cout << "Receive failed with error " << WSAGetLastError() << endl;
return -1;
}
else if (iResult ==0 )
{
cout << "Receive data stopped. There " << left << " bytes unreceived" << endl;
break;
}
else
{
cout << "Receive data : " << iResult << " bytes" << endl;
rec_file.write(Recvb, left);
left = 0;
}
}
}
//接收文件长度数据
iResult = recv(s, (char*)&len_tran, 4, 0);
if (iResult != 4)
{
if (iResult == -1)
{
cout << "Receive failed with error " << WSAGetLastError() << endl;
return -1;
}
else
{
cout << "Length data is not complete. Connection closed\n" << endl;
return -1;
}
}
recvlen =ntohl( len_tran);
cout << "The length of file to receive is " << recvlen << "\n" << endl;
iResult = recv(ConnectSocket, RecvBuffer, sizeof(RecvBuffer), 0);
if (iResult == SOCKET_ERROR || iResult == 0)
{
cout << "Client(" << inet_ntoa(information.addrinfo.sin_addr) << " : " << information.addrinfo.sin_port << ") Exited" << endl;
//每次如果出现任何错误,continue会回到这里,因为这个时候客户端已经关闭,就可以统一的closesocket关闭连接同时返回
closesocket(ConnectSocket);
return -1;
}
服务端
从图中可以看出:
服务端可以得到客户端的地址和端口信息、可以打印出即将接受的文件名、文件的长度。同时在文件接收完毕的时候给出提示,打印出文件内容。最后给客户端发送确认信息。客户端在得到确认之后退出。
当传输文件过大的时候,服务端循环接受数据,并且在每次接受的时候,打印出相关信息。
并且
在客户端的文件目录下,可以看到传过来的数据,并且可以正常打开
由此,实验结果达到了要求
#define _WINSOCK_DEPRECATED_NO_WARNINGS
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <WinSock2.h>
#include <WS2tcpip.h>
#include <iostream>
#include <stdlib.h>
#include <stdint.h>
#include <fstream>
#include<io.h>
#include <stdint.h>
using namespace std;
#pragma comment (lib,"ws2_32.lib")
using namespace std;
//缓存区长度
#define MAX_LEN 100000
int __cdecl main(int argc, char* argv[])
{
WSADATA ws;
SOCKET ConnectSocket = INVALID_SOCKET;
struct sockaddr_in Server_addr;
int iResult = 0;
int Addrlen = 0;
HANDLE hThread = NULL;
char Sendbuffer[MAX_LEN];
char Recvbuffer[MAX_LEN];
//检查参数个数
if (argc != 4)
{
cout << "Need enter target IP, port and the file name to transmit !" << endl;
return -1;
}
int PORT = atoi(argv[2]);
//初始化 socket
iResult = WSAStartup(MAKEWORD(2, 2), &ws);
if (iResult != 0)
{
cout << "Initiate failed with error: " << GetLastError() << endl;
WSACleanup();
return -1;
}
//创建 socket
ConnectSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (ConnectSocket == INVALID_SOCKET)
{
cout << "Create Client socket failed with error: " << WSAGetLastError() << endl;
WSACleanup();
return -1;
}
Server_addr.sin_family = AF_INET;
Server_addr.sin_addr.s_addr = inet_addr(argv[1]);
Server_addr.sin_port = htons(PORT);
memset(Server_addr.sin_zero, 0x00, 8);
//连接 socket
iResult = connect(ConnectSocket, (struct sockaddr*)&Server_addr, sizeof(Server_addr));
if (iResult != 0)
{
cout << "Connect with error: " << WSAGetLastError() << endl;
closesocket(ConnectSocket);
WSACleanup();
return -1;
}
else
{
cout << "Connect successfully!" << endl;
}
char filebuf[MAX_LEN + 1]; //文件内容存储数组
//传输文件,先传输文件名,再传输文件长度,最后传输文件内容
while (true)
{
cout << "Ready to send file" << endl;
int len3 = strlen(argv[3]);
//对文件名传输进行处理
char filename[MAX_PATH];
int i = 0;
for (i = 0; i < len3; i++)
{
filename[i] = argv[3][i];
}
filename[i++] = ‘#‘;
//传输文件名
iResult = send(ConnectSocket, filename, strlen(filename), 0);
if (iResult == SOCKET_ERROR)
{
cout << "Send Filename : " << Sendbuffer << " with error " << WSAGetLastError() << "\n" << endl;
break;
}
//确定文件的大小
int len;
FILE* fp;
if(fp = fopen(argv[3], "r"))
{
fseek(fp, 0, SEEK_END);
printf("%ld\n", ftell(fp));
len = ftell(fp);
fclose(fp);
}
else
{
cout << "Error" << endl;
}
//以二进制文件形式读取文件
ifstream sourcefile(argv[3], ios::in | ios::binary);
int filelen = len;
int filelen_net = htonl(filelen);
//传输内容长度
cout << "Sending the length of file: " << filelen << "\n" << endl;
iResult = send(ConnectSocket, (char*)&filelen_net, 4, 0);
if (iResult == SOCKET_ERROR)
{
cout << "Send file length failed with error " << WSAGetLastError() << endl;
break;
}
//传输文件内容
cout << "Ready to send file!" << endl;
int left = filelen;
while (left>0)
{
if (left > MAX_LEN)
{
sourcefile.read(filebuf, MAX_LEN);
iResult = send(ConnectSocket, filebuf, MAX_LEN, 0);
if (iResult == SOCKET_ERROR)
{
cout << "Send file content failed with error " << WSAGetLastError() << "\n" << endl;
break;
}
left -= MAX_LEN;
}
else
{
sourcefile.read(filebuf, left);
iResult = send(ConnectSocket, filebuf, left, 0);
left = 0;
if (iResult == SOCKET_ERROR)
{
cout << "Send file content failed with error " << WSAGetLastError() << "\n" << endl;
break;
}
}
}
sourcefile.close();
if (left != 0)
{
cout << "Send file content failed with error " << WSAGetLastError() << "\n" << endl;
cout << "Client Exit..." << endl;
break;
}
//判断来自客户端的返回信息
iResult = recv(ConnectSocket, Recvbuffer, sizeof(Recvbuffer), 0);
Recvbuffer[iResult] = ‘\0‘;
if (iResult == SOCKET_ERROR)
{
cout << "Failed to receive confirm from server!\n" << endl;
break;
}
else if (strcmp(Recvbuffer, "OK\0") == 0)
{
cout << "Received confirm from server: " << Recvbuffer << "\nSending file succeed!\n" << endl;
break;
}
}
closesocket(ConnectSocket);
WSACleanup();
system("pause");
return 0;
}
#define _WINSOCK_DEPRECATED_NO_WARNINGS
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <WinSock2.h>
#include <WS2tcpip.h>
#include <iostream>
#include <stdlib.h>
#include <stdint.h>
#include <fstream>
using namespace std;
#pragma comment (lib,"ws2_32.lib")
#define PORT 4000
#define IP_ADDR "0.0.0.0"
#define MAX_LEN 100000
//定长数据传输
int recvn(SOCKET s, char *recvbuf, unsigned int fixedlen)
{
int iResult;
int cnt; //记录当前待接受的数量
cnt = fixedlen;
while (cnt > 0)
{
iResult = recv(s, recvbuf, cnt, 0);
if (iResult < 0)
{
cout << "Receive failed with error :" << WSAGetLastError() << endl;
return -1;
}
if (iResult == 0)
{
cout << "Data is not as long as fixed. Connection closed" << endl;
return fixedlen - cnt;
}
recvbuf += iResult;
cnt -= iResult;
}
return fixedlen;
}
//变长内容传输
int recvvl(SOCKET s, char*filename)
{
int iResult;
long recvlen;
int len_tran;
char Recvb[MAX_LEN];
//接收文件长度数据
iResult = recv(s, (char*)&len_tran, 4, 0);
if (iResult != 4)
{
if (iResult == -1)
{
cout << "Receive failed with error " << WSAGetLastError() << endl;
return -1;
}
else
{
cout << "Length data is not complete. Connection closed\n" << endl;
return -1;
}
}
recvlen =ntohl( len_tran);
cout << "The length of file to receive is " << recvlen << "\n" << endl;
ofstream rec_file;
rec_file.open(filename, ios::binary);
int left = recvlen;
while (left > 0)
{
if (left > MAX_LEN)
{
iResult = recvn(s, Recvb, MAX_LEN);
if (iResult == -1)
{
cout << "Receive failed with error " << WSAGetLastError() << endl;
return -1;
}
else if (iResult == 0)
{
cout << "Receive data stopped. There "<<left<<" bytes unreceived" << endl;
break;
}
else
{
cout << "Receive partial data : " << iResult << " bytes" << endl;
rec_file.write(Recvb, MAX_LEN);
left -= MAX_LEN;
}
}
else
{
iResult = recvn(s, Recvb, left);
if (iResult == -1)
{
cout << "Receive failed with error " << WSAGetLastError() << endl;
return -1;
}
else if (iResult ==0 )
{
cout << "Receive data stopped. There " << left << " bytes unreceived" << endl;
break;
}
else
{
cout << "Receive data : " << iResult << " bytes" << endl;
rec_file.write(Recvb, left);
left = 0;
}
}
}
if (left == 0)
{
cout << "Receive all the data\n" << endl;
}
return recvlen;
}
//自己定义的结构体,用于多线程传参
struct my_para
{
SOCKET connect_socket;
struct sockaddr_in addrinfo;
};
//多线程函数
DWORD WINAPI ClientThread(LPVOID lpparameter)
{
struct my_para information = *(struct my_para *)lpparameter;
int iResult = 0;
char RecvBuffer[MAX_LEN];
SOCKET ConnectSocket = information.connect_socket;
int filelength = 0;
char filename[MAX_PATH] = { 0 };
while (TRUE)
{
//接收名字
iResult = recv(ConnectSocket, RecvBuffer, sizeof(RecvBuffer), 0);
if (iResult == SOCKET_ERROR || iResult == 0)
{
cout << "Client(" << inet_ntoa(information.addrinfo.sin_addr) << " : " << information.addrinfo.sin_port << ") Exited" << endl;
//每次如果出现任何错误,continue会回到这里,因为这个时候客户端已经关闭,就可以统一的closesocket关闭连接同时返回
closesocket(ConnectSocket);
return -1;
}
//对接收的文件名进行处理,存储下来,在后面本地保存时使用
int i = 0;
for (i; RecvBuffer[i] != ‘#‘; i++)
{
filename[i] = RecvBuffer[i];
}
filename[i] = ‘\0‘;
cout << "The file " << filename << " is to receive!\n" << endl;
//接收文件
cout << "Ready to receive file!\n" << endl;
iResult = recvvl(ConnectSocket, filename);
if (iResult == 0 || iResult == -1)
{
cout << "Send file failed !\n\n\n" << endl;
continue;
}
//文件传输成功时,返回OK信息
char returnmessage[] = "OK\0";
iResult = send(ConnectSocket, returnmessage, strlen(returnmessage), 0);
if (iResult == SOCKET_ERROR)
{
cout << "Return confirm message with error " << WSAGetLastError() << endl;
continue;
}
else
{
cout << "Return success!\n" << endl;
}
}
closesocket(ConnectSocket);
return 0;
}
int main(int argc, char * argv[])
{
WSADATA ws;
SOCKET ServerSocket = INVALID_SOCKET, ClientSocket = INVALID_SOCKET;
struct sockaddr_in LocalAddr, ClientAddr;
int iResult = 0;
int Addrlen = 0;
HANDLE hThread = NULL;
//Initiate
iResult = WSAStartup(MAKEWORD(2, 2), &ws);
if (iResult != 0)
{
cout << "Initiate failed with error: " << WSAGetLastError() << endl;
return -1;
}
//create socket
ServerSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (ServerSocket == INVALID_SOCKET)
{
cout << "create socket failed with error: " << WSAGetLastError() << endl;
WSACleanup();
return -1;
}
LocalAddr.sin_family = AF_INET;
LocalAddr.sin_addr.s_addr = inet_addr(IP_ADDR);
LocalAddr.sin_port = htons(PORT);
memset(LocalAddr.sin_zero, 0x00, 8);
//bind socket
iResult = bind(ServerSocket, (struct sockaddr *)&LocalAddr, sizeof(LocalAddr));
if (iResult != 0)
{
cout << "Bind socket failed: " << WSAGetLastError() << endl;
closesocket(ServerSocket);
WSACleanup();
return -1;
}
//listen
iResult = listen(ServerSocket, 10);
if (iResult != 0)
{
cout << "Listen socket failed with error: " << WSAGetLastError() << endl;
closesocket(ServerSocket);
WSACleanup();
return -1;
}
cout << "Server is already setup!\n" << endl;
SOCKET acc_sock;
while (TRUE)
{
Addrlen = sizeof(ClientAddr);
acc_sock = accept(ServerSocket, (struct sockaddr*)&ClientAddr, &Addrlen);
if (acc_sock < 0)
{
cout << "Accept failed with error: " << WSAGetLastError() << endl;
break;
}
char *addr_temp = inet_ntoa(ClientAddr.sin_addr);
cout << "Client has already connected! (" << addr_temp << " : " << ClientAddr.sin_port << ")\n" << endl;
struct my_para temp;
temp.addrinfo = ClientAddr;
temp.connect_socket = acc_sock;
hThread = CreateThread(NULL, 0, ClientThread, (LPVOID)&temp, 0, NULL);
if (hThread == NULL)
{
cout << "Create Thread failed!" << endl;
break;
}
CloseHandle(hThread);
}
closesocket(ServerSocket);
closesocket(ClientSocket);
WSACleanup();
system("pause");
return 0;
}
原文:https://www.cnblogs.com/volva/p/11815075.html