Windows Socket编程之UDP实现大文件的传输

前言:

TCP版本请参考本人博客:http://blog.csdn.net/luchengtao11/article/details/71012580

本文所述代码工程托管在Github:https://github.com/Wuchenwcf/MyCode/tree/master/C%2B%2B/Socket

本文实现以下功能:

在客户端,用户选择本地的某个文件,并发送到服务器端。
在服务器端,接收客户端传输的数据流,并按IP 地址保存在服务器端(文
件名重复的,可以覆盖)。
如果传输过程中服务器端发现客户端断开,服务器端应删除文件,并在屏幕
上提示,如“IP:1.2.3.4 发来abcd.txt 文件过程中失去连接。”。如果客户端发
现服务器端不工作,客户端应有提示“服务器1.2.3.5:62345 失去连接”。

一、UDP传输流程图


二、代码实现

1.1.FileHelper用来进行与文件相关的操作

#include<stdio.h>
#include<stdlib.h>
#include <WINSOCK2.H>
#include <STDIO.H>
#pragma  comment(lib,"ws2_32.lib")

class FileHelper
{
private:
	FILE *f;
	char path_buffer[_MAX_PATH];
	char drive[_MAX_DRIVE];
	char dir[_MAX_DIR];
	char fname[_MAX_FNAME];
	char ext[_MAX_EXT];

public:
	FILE * selectfile()
	{
		printf("请输入要传送的文件名\n");
		scanf("%s",path_buffer);

		if (f=fopen(path_buffer,"rb"))
		{
			printf("文件打开成功\n");
			return f;
		}
		else
		{
			printf("文件不存在,请重新输入\n");
			return selectfile();
		}
	}

	char * getFileName()
	{
		_splitpath(path_buffer, drive, dir, fname, ext);
		return strcat(fname, ext);
	}
	FILE * createFile(char *name)
	{
		remove(name);
		if (f = fopen(name, "ab"))
		{
			printf("文件创建成功\n");

		}
		else
		{
			printf("文件创建失败\n");
		}
		return f;
	}

	bool createDir(char *dir)
	{
		char head[MAX_PATH] = "md ";
		return system(strcat(head, dir));
	}





};

2.Client端
#pragma comment(lib,"Ws2_32.lib")

#include<WinSock2.h>
#include<WS2tcpip.h>
#include<stdio.h>
#include<Windows.h>

#include"FileHelper.h"

int main()
{

	WORD wVersionRequested;
	WSADATA wsaData;
	char sendData[BUFSIZ]="ÄãºÃ£¡\n";
	char beginData[BUFSIZ]="Begin\n";
	char overData[BUFSIZ]="Over\n";
	char Filename[BUFSIZ]={};
	FileHelper fh;
	int err;
	wVersionRequested = MAKEWORD(2, 2);

	err = WSAStartup(wVersionRequested, &wsaData);
	if (err != 0) {
		/* Tell the user that we could not find a usable */
		/* Winsock DLL.                                  */
		printf("WSAStartup failed with error: %d\n", err);
		return 1;
	}

	if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2) {
		/* Tell the user that we could not find a usable */
		/* WinSock DLL.                                  */
		printf("Could not find a usable version of Winsock.dll\n");
		WSACleanup();
		return 1;
	}

	SOCKADDR_IN addrServ;
	addrServ.sin_addr.S_un.S_addr=inet_addr("127.0.0.1");
	addrServ.sin_family=AF_INET;
	addrServ.sin_port=htons(4999);
	while (true)
	{
		SOCKET socketClient=socket(AF_INET,SOCK_DGRAM,0);
		FILE *f=fh.selectfile();
		sendto(socketClient,beginData,BUFSIZ,0,(SOCKADDR*)&addrServ,sizeof(SOCKADDR));
		strcpy(Filename,fh.getFileName());
		sendto(socketClient,Filename,BUFSIZ,0,(SOCKADDR*)&addrServ,sizeof(SOCKADDR));
		int count=0;
		int sum=0;
		while ((count=fread(sendData,1,BUFSIZ,f))>0)
		{
			Sleep(1);
			printf("%d\n",sum+=count);
			sendto(socketClient,sendData,BUFSIZ,0,(SOCKADDR*)&addrServ,sizeof(SOCKADDR));
		}
		sendto(socketClient,overData,BUFSIZ,0,(SOCKADDR*)&addrServ,sizeof(SOCKADDR));
		closesocket(socketClient);
	}
	WSACleanup();
	return 0;

}

3.Servet端

#pragma comment(lib,"Ws2_32.lib")
#include<WinSock2.h>
#include<WS2tcpip.h>
#include<stdio.h>
#include<Windows.h>
#include "FileHelper.h"

int main()
{
	WORD wVersionRequested;
	WSADATA wsaData;

	FileHelper fh;
	int err;
	wVersionRequested=MAKEWORD(2,2);
	err=WSAStartup(wVersionRequested,&wsaData);
	if (err!=0)
	{
		printf("WSAStartup failed with error:%d\n",err);
		return -1;
	}
	if (LOBYTE(wsaData.wVersion)!=2||HIBYTE(wsaData.wVersion)!=2)
	{
		printf("Could not find a usable version of Winsock.dll\n");
		WSACleanup();
		return -1;
	}
	SOCKET socketServer=socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP);
	SOCKADDR_IN addrServ;
	addrServ.sin_addr.S_un.S_addr=htonl(INADDR_ANY);//指定0.0.0.0地址,表示任意地址
	addrServ.sin_family=AF_INET;//表示IPv4的套接字类型
	addrServ.sin_port=htons(4999);
	bind(socketServer,(SOCKADDR*)&addrServ,sizeof(SOCKADDR));
	SOCKADDR_IN addrClient;
	int length=sizeof(SOCKADDR);
	char recvBuf[BUFSIZ]={};
	int rev=0;
	while (true)
	{
		DWORD TIME_OUT=10;
		char sendData[BUFSIZ]="你好!\n";
		char beginData[BUFSIZ]="Begin\n";
		char overData[BUFSIZ]="Over\n";
		char Filename[BUFSIZ]={};
		char ClientAddr[BUFSIZ]={};
		char FromName[BUFSIZ]={};
		FILE *f=NULL;
		if(err=setsockopt(socketServer,SOL_SOCKET,SO_SNDTIMEO,(char *)&TIME_OUT,sizeof(TIME_OUT)))
		{
			printf("失败!\n");
		};
		printf("%d\n",err);
		recvfrom(socketServer,recvBuf,BUFSIZ,0,(SOCKADDR*)&addrClient,&length);
		if (strcmp(recvBuf,beginData)==0)
		{

			recvfrom(socketServer,recvBuf,BUFSIZ,0,(SOCKADDR*)&addrClient,&length);
			strcpy(ClientAddr,inet_ntoa(addrClient.sin_addr));
			strcpy(FromName,recvBuf);
			fh.createDir(ClientAddr);
			strcpy(Filename,ClientAddr);
			strcat(Filename,"\\");
			strcat(Filename,recvBuf);
			f=fh.createFile(Filename);

		}
		int sum=0;
		while((rev=recvfrom(socketServer,recvBuf,BUFSIZ,0,(SOCKADDR*)&addrClient,&length))>0)
		{
			if (strcmp(overData,recvBuf)==0)
			{
				printf("文件%s传输成功!\n",FromName);
				fclose(f);
				break;
			}
		//	printf(recvBuf);
			fwrite(recvBuf,1,rev,f);
			printf("%db\n",sum+=rev);
		}

		if (rev<0||strcmp(overData,recvBuf)!=0)
		{
			printf("IP:%s发来的%s传输过程中失去连接\n",addrClient,FromName);
			fclose(f);
			remove(Filename);
		}

	}

	closesocket(socketServer);
	WSACleanup();
	return 0;

}


猜你喜欢

转载自blog.csdn.net/luchengtao11/article/details/71016222