ftp并发套接字编程
基于ftp的多线程Socket编程,服务器端和客户端可以互传文件。
编译环境:VS2019,VC++
先在D盘添加file_server和file_client文件夹,在里面可以新建一些文件,方便客户端上传与下载。
有注释,贴上源码,供大家学习参考。
服务器端 Server.cpp
#include <windows.h>
#include <stdio.h>
#include<iostream>
#include <string.h>
#pragma comment (lib,"ws2_32")
using namespace std;
#define BUF_SIZE 1024
void RecvFile(char name[], SOCKET s) {
char FileName[MAXBYTE] = "";
sprintf(FileName, "D:\\file_server\\%s", name);
char info[BUF_SIZE];
recv(s, info, BUF_SIZE, 0);
cout << info << endl;
if (!strcmp(info, "传输文件失败, 文件不存在!\n")) {
}
else {
DWORD dwWrite;
HANDLE hFile = CreateFile(FileName, GENERIC_WRITE, 0, 0, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
char szBufferfile[BUF_SIZE] = { NULL };
char ok[BUF_SIZE] = { NULL };
while (true) {
int read = recv(s, szBufferfile, BUF_SIZE, 0);
if (!strcmp(ok, szBufferfile)) {
printf("接收文件成功!!!\n"); break;
}
bool bRet = WriteFile(hFile, szBufferfile, read, &dwWrite, NULL);
}
CloseHandle(hFile);
}
}
void Sender(char name[], SOCKET clientSock) {
char FileName[MAXBYTE] = "";
sprintf(FileName, "D:\\file_server\\%s", name);
char ok[BUF_SIZE] = { NULL };
char SendBuf[BUF_SIZE] = { NULL };
DWORD dwRead;
HANDLE hFile = CreateFile(FileName, GENERIC_READ, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
if (hFile == INVALID_HANDLE_VALUE) {
send(clientSock, "传输文件失败, 文件不存在!\n", BUF_SIZE, 0);
}
else {
send(clientSock, "开始接收文件\n", BUF_SIZE, 0);
while (TRUE) {
bool bRet = ReadFile(hFile, SendBuf, BUF_SIZE, &dwRead, NULL);
if (bRet == FALSE) {
//MessageBox(NULL, "Read Buf ERROR!", "Error", MB_OK);
CloseHandle(hFile);
break;
}
else if (dwRead == 0)
{
//MessageBox(NULL, "Send file OK!", "OK", MB_OK);
CloseHandle(hFile);
printf("发送文件成功!!!\n");
send(clientSock, ok, BUF_SIZE, 0);
break;
}
else
{
send(clientSock, SendBuf, BUF_SIZE, 0);
}
}
}
}
DWORD WINAPI ClientThread(LPVOID IpParam) {
SOCKET clientSock = (SOCKET)IpParam;
printf("与客户端取得连接,套接字编号为%u\n", clientSock);
char RecvBuf[MAXBYTE];
char FileName[MAXBYTE] = { NULL };
int read = 0;
char getcheck[6] = { "down" };
char upcheck[6] = { "up" };
while (true) {
memset(RecvBuf, 0, MAXBYTE);//与客户端进行文字通信
read = recv(clientSock, RecvBuf, MAXBYTE, 0);
if (read == -1) break;
printf(RecvBuf);
printf("\n");
if (!strcmp(RecvBuf, getcheck)) { // get 下载文件
memset(FileName, 0, MAXBYTE);
read = recv(clientSock, FileName, MAXBYTE, 0);
if (read == -1) break;
printf("%s\r\n", FileName);
Sender(FileName, clientSock);
}
else if (!strcmp(RecvBuf, upcheck)) {
memset(FileName, 0, MAXBYTE);
recv(clientSock, FileName, MAXBYTE, 0);
RecvFile(FileName, clientSock);
}
else {
send(clientSock, "无效的命令,请重新输入..\n", MAXBYTE, NULL);
}
}
closesocket(clientSock);
return 0;
}
int main(int argc, char* argv[]) {
WSADATA wsaData;
WSAStartup(MAKEWORD(2, 2), &wsaData);
SOCKET s = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); //套接字s用于监听
sockaddr_in sockaddr;
sockaddr.sin_family = PF_INET;
sockaddr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
sockaddr.sin_port = htons(827);
bind(s, (SOCKADDR*)&sockaddr, sizeof(sockaddr)); //绑定套接字 ip,端口号
SOCKADDR clientAddr = { 0 };
int nSize = sizeof(SOCKADDR);
SOCKET clientSock;
listen(s, 1);
//循环接受客户端连接请求,并生成线程去处理:
printf("I'm server\n");
while(1) {
//等待接受客户端控制连接请求
clientSock = accept(s, (SOCKADDR*)&clientAddr, &nSize);
//创建一个线程来处理相应客户端的请求:
DWORD dwThreadId, dwThrdParam = 1;
HANDLE hThread;
hThread = CreateThread(
NULL, //无需安全性的继承
0, //默认线程栈大小
ClientThread, //线程入口函数
(LPVOID)clientSock, //线程入口函数的参数
0, //立即启动线程
&dwThreadId); //返回线程的id值
//检查返回值是否创建线程成功
if (hThread == NULL) {
printf("创建线程失败。\n");
closesocket(s);
}
CloseHandle(hThread);
}
closesocket(clientSock);
closesocket(s);
WSACleanup();
return 0;
}
客户端 Client.cpp
#include<iostream>
#include<winsock2.h>
#pragma comment (lib,"ws2_32")
using namespace std;
#define BUF_SIZE 1024
void RecvFile(char name[], SOCKET s) {
char FileName[MAXBYTE] = "";
sprintf(FileName, "D:\\file_client\\%s", name);
char info[BUF_SIZE];
recv(s, info, BUF_SIZE, 0);
cout << info << endl;
if (!strcmp(info, "传输文件失败, 文件不存在!\n")) {
}
else {
DWORD dwWrite;
HANDLE hFile = CreateFile(FileName, GENERIC_WRITE, 0, 0, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
char szBufferfile[BUF_SIZE] = { NULL };
char ok[BUF_SIZE] = { NULL };
while (true) {
int read = recv(s, szBufferfile, BUF_SIZE, 0);
if (!strcmp(ok, szBufferfile)) {
printf("已接收到文件!!!\n"); break;
}
bool bRet = WriteFile(hFile, szBufferfile, read, &dwWrite, NULL);
}
CloseHandle(hFile);
printf("写入文件成功!!!\n");
}
}
void Sender(char name[], SOCKET clientSock) {
char FileName[MAXBYTE] = "";
sprintf(FileName, "D:\\file_client\\%s", name);
char ok[BUF_SIZE] = { NULL };
char SendBuf[BUF_SIZE] = { NULL };
DWORD dwRead;
HANDLE hFile = CreateFile(FileName, GENERIC_READ, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
if (hFile == INVALID_HANDLE_VALUE) {
cout << "传输文件失败, 文件不存在!" << endl;
send(clientSock, "传输文件失败, 文件不存在!\n", BUF_SIZE, 0);
}
else {
send(clientSock, "开始接收文件...\n", BUF_SIZE, 0);
while (TRUE) {
bool bRet = ReadFile(hFile, SendBuf, BUF_SIZE, &dwRead, NULL);
if (bRet == FALSE) {
//MessageBox(NULL, "Read Buf ERROR!", "Error", MB_OK);
CloseHandle(hFile);
break;
}
else if (dwRead == 0)
{
//MessageBox(NULL, "Send file OK!", "OK", MB_OK);
CloseHandle(hFile);
printf("发送文件成功!!!\r\n");
send(clientSock, ok, BUF_SIZE, 0);
break;
}
else
{
send(clientSock, SendBuf, BUF_SIZE, 0);
}
}
}
}
int main(int argc, char* argv[])
{
WSADATA wsaData;
WSAStartup(MAKEWORD(2, 2), &wsaData);
SOCKET s = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); //创建套接字
sockaddr_in sockAddr;
sockAddr.sin_family = PF_INET;
sockAddr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
sockAddr.sin_port = htons(827);
char SendBuf[MAXBYTE];
char szBuffer[MAXBYTE] = { NULL };
char FileName[MAXBYTE] = { NULL };
char getcheck[6] = { "down" };
char upcheck[6] = { "up" };
char bye[6] = { "exit" };
printf("I'm Client\n1)down:从服务端下载文件\n2)up:上传文件到服务器\n3)exit:退出\n");
//cout << "Server:" << endl;
connect(s, (SOCKADDR*)&sockAddr, sizeof(SOCKADDR)); //给服务器端发送TCP链接请求
while (TRUE) {
cout << "Client:";
memset(SendBuf, 0, MAXBYTE);
cin >> SendBuf;
if (!strcmp(SendBuf, getcheck)) {
send(s, SendBuf, MAXBYTE, NULL);
cout << "filename:";
memset(FileName, 0, MAXBYTE);
cin >> FileName;
send(s, FileName, MAXBYTE, NULL);
RecvFile(FileName, s);
continue;
}
else if (!strcmp(SendBuf, upcheck)) {
send(s, SendBuf, MAXBYTE, NULL);
cout << "filename:";
memset(FileName, 0, MAXBYTE);
cin >> FileName;
send(s, FileName, MAXBYTE, NULL);
Sender(FileName, s);
continue;
}
else if (!strcmp(SendBuf, bye)) {
cout << "已退出。\n" << endl;
break;
}
send(s, SendBuf, MAXBYTE, NULL);
memset(szBuffer, 0, MAXBYTE);
memset(SendBuf, 0, MAXBYTE);
recv(s, szBuffer, MAXBYTE, NULL);
cout << szBuffer;
}
closesocket(s);
WSACleanup();
return 0;
}