⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 transferfile.c

📁 刚学VC时写的文件传输程序,全部用SocketAPI编写
💻 C
字号:
#ifndef	__TRANSFER_FILE_C__
#define	__TRANSFER_FILE_C__

#include <WinSock.h>
#include "TransferFile.h"
#include "net_list.h"

//#pragma comment(lib,"ws2_32.lib")


LPWSADATA					inet_WsaData;
PTRAN_LIST					inet_TransList = NULL;
SOCKET						inet_Listen_Socket = INVALID_SOCKET;
PCHAR						inet_Local_Dir = NULL;


void net_InsertItemIntoList(PTRAN_THREAD item)
{
	PTRAN_LIST p = inet_TransList, pt = NULL;
	while (p)
	{
		pt = p;
		p = p->next;
	}
	p = malloc(sizeof(TRAN_LIST));
	p->context = item;
	p->next = NULL;
	if (!pt)
	{
		inet_TransList = p;
	}
	else
	{
		pt->next = p;
	}
}

PTRAN_LIST net_SearchItemFromListByItem(PTRAN_THREAD item)
{
	PTRAN_LIST p = inet_TransList;
	while (p)
	{
		if (p->context == item)
		{
			break;
		}
		p = p->next;
	}
	return p;
}


PTRAN_LIST net_SearchItemFromListBySocket(SOCKET sock)
{
	PTRAN_LIST p = inet_TransList;
	while (p)
	{
		if (p->context->sock == sock)
		{
			break;
		}
		p = p->next;
	}
	return p;
}


void net_DisposeListItemByItem(PTRAN_THREAD item)
{
	DWORD dwExitCode;
	PTRAN_LIST p = inet_TransList, pt = NULL;
	while (p)
	{
		if (p->context == item)
		{
			if (!pt)	//delete the header
			{
				inet_TransList = p->next;
			}
			else
			if (!p->next)	//delete the tail
			{
				if (pt)
				{
					pt->next = NULL;
				}
			}
			else
			{
				pt->next = p->next;
			}
			if (p->context)
			{
				if (p->context->ctrl)
				{
					free(p->context->ctrl);
				}
				if (p->context->hfile != INVALID_HANDLE_VALUE)
				{
					CloseHandle(p->context->hfile);
					p->context->hfile = INVALID_HANDLE_VALUE;
				}
				if (p->context->sock != INVALID_SOCKET)
				{
					closesocket(p->context->sock);
					p->context->sock = INVALID_SOCKET;
				}
				if (p->context->thread != INVALID_HANDLE_VALUE)
				{
					if (GetExitCodeThread(p->context->thread, &dwExitCode))
					{
						TerminateThread(p->context->thread, dwExitCode);
					}
					p->context->thread = INVALID_HANDLE_VALUE;
				}
				free(p->context);
			}
			free(p);
			break;
		}
		pt = p;
		p = p->next;
	}
}

void net_RemoveItemFromListBySocket(SOCKET item)
{
	PTRAN_LIST p = inet_TransList, pt = NULL;
	while (p)
	{
		if (p->context->sock == item)
		{
			net_DisposeListItemByItem(p->context);
			break;
		}
		pt = p;
		p = p->next;
	}
}

void net_RemoveList()
{
	PTRAN_LIST p = inet_TransList;
	while (p)
	{
		net_DisposeListItemByItem(p->context);
		p = inet_TransList;
	}
}


DWORD inet_Accept_Connect(SOCKET sock)
{
	PTRAN_THREAD p = malloc(sizeof(TRAN_THREAD));
	int len;
	len = sizeof(SOCKADDR_IN);
	p->ctrl = NULL;
	p->hfile = INVALID_HANDLE_VALUE;
	p->thread = INVALID_HANDLE_VALUE;
	p->sock = accept(sock, (struct sockaddr *)&p->addr, &len);
	net_InsertItemIntoList(p);
	return RET_SUCCESS;
}


WORD inet_Extract_FileName_From_Buffer(PBYTE buf, WORD len, char * fname, PWORD fnlen, PDWORD fsize)			//get file name & length
{
	WORD i = 0;
	if (len < 5)
	{
		return RET_FAILURE;
	}
	//get file size from buffer
	*fsize = (DWORD)(*(buf + 0));
	*fsize += (DWORD)(*(buf + 1)) * 256;
	*fsize += (DWORD)(*(buf + 2)) * 256 * 256;
	*fsize += (DWORD)(*(buf + 3)) * 256 * 256 * 256;
	//get filename from buffer
	memcpy(fname, buf + 4, len - 4);
	*fnlen = strlen(fname);
	return RET_SUCCESS;
}


BYTE inet_Calc_BCC(PBYTE buf, WORD len)
{
	BYTE ret = 0;
	while (len > 0)
	{
		ret ^= *buf++;
		len --;
	}
	return ret;
}

void inet_Reply_Remote(SOCKET s, PTF_COMMAND pcmd)
{
	WORD len = COMMAND_HEADER_LENGTH + pcmd->low + (WORD)pcmd->high * 256;
	PBYTE buf = malloc(len);
	memcpy(buf, pcmd, COMMAND_HEADER_LENGTH - 1);
	if ((pcmd->low + (WORD)pcmd->high * 256 > 0) && (pcmd->data))
	{
		memcpy(buf + COMMAND_HEADER_LENGTH - 1, pcmd->data, len - COMMAND_HEADER_LENGTH);
	}
//	*(buf + len - 1) = inet_Calc_BCC(pcmd->data, (WORD)(len - COMMAND_HEADER_LENGTH));
	send(s, buf, len, 0);
	free(buf);
}



void inet_Save_File_To_Local(SOCKET s, PTF_COMMAND pcmd)
{
	char * fname = NULL;
	PWORD fnlen = 0;
	char * fdir = NULL;
	WORD len = (WORD)pcmd->low + (WORD)pcmd->high * 256;
	PDWORD fsize = 0;
	DWORD dwRead = 0;
	PTRAN_LIST p = net_SearchItemFromListBySocket(s);
	if (p)
	{
		if (!p->context->ctrl)
		{
			p->context->ctrl = malloc(sizeof(TRAN_CTRL));
			memset(p->context->ctrl, 0, sizeof(TRAN_CTRL));
		}
		fname = malloc(1024);
		memset(fname, 0, 1024);
		fnlen = malloc(sizeof(WORD));
		fsize = malloc(sizeof(DWORD));
		if (p->context->hfile == INVALID_HANDLE_VALUE)
		{
			if (inet_Extract_FileName_From_Buffer(
								pcmd->data,
								len,
								fname,
								fnlen,
								fsize) == 0)
			{
				len = strlen(inet_Local_Dir) + 1 + *fsize + 1;
				fdir = malloc(len);
				memset(fdir, 0, len);
				memcpy(fdir, inet_Local_Dir, strlen(inet_Local_Dir));
				if (*(inet_Local_Dir + strlen(inet_Local_Dir) - 1) != '\\')
				{
					*(fdir + strlen(inet_Local_Dir)) = '\\';
					memcpy(fdir + strlen(inet_Local_Dir) + 1, fname, *fnlen);
				}
				else
				{
					memcpy(fdir + strlen(inet_Local_Dir), fname, *fnlen);
				}
				memset(fname, 0, 1024);
				memcpy(fname, fdir, strlen(fdir));
				free(fdir);
			}
			p->context->hfile = CreateFile(
												fname,
												GENERIC_READ | GENERIC_WRITE,
												FILE_SHARE_READ | FILE_SHARE_WRITE,
												NULL,
												OPEN_ALWAYS,
												FILE_ATTRIBUTE_NORMAL,
												NULL);
			if (p->context->ctrl->status == TRAN_STOP)
			{
				if (pcmd->data)
				{
					free(pcmd->data);
				}
				pcmd->opcode = RET_SUCCESS;
				p->context->ctrl->fsize = *fsize;
				pcmd->data = malloc(1);
				pcmd->low = 1;
				pcmd->high = 0;
				*(pcmd->data + 0) = TRAN_SYN;
				inet_Reply_Remote(p->context->sock, pcmd);
				p->context->ctrl->status = TRAN_START;
			}
		}
		else
		{
			WriteFile(
						p->context->hfile,
						pcmd->data,
						pcmd->low + pcmd->high * 256,
						&dwRead,
						NULL);

			pcmd->low = 0;
			pcmd->high = 0;
			free(pcmd->data);
			pcmd->data = NULL;
			pcmd->opcode = RET_SUCCESS;

			inet_Reply_Remote(p->context->sock, pcmd);
			p->context->ctrl->offset += dwRead;
			if (p->context->ctrl->offset == p->context->ctrl->fsize)
			{
				CloseHandle(p->context->hfile);
				p->context->hfile = INVALID_HANDLE_VALUE;
				free(p->context->ctrl);
				p->context->ctrl = NULL;
			}
		}
		free(fname);
		free(fnlen);
		free(fsize);
	}
}

DWORD inet_Process_Remote_Command(SOCKET s, PTF_COMMAND pcmd)
{
	switch (pcmd->cmd)
	{
	case	TRAN_REQ_READ:			//remote request read data from local
		switch (pcmd->opcode)
		{
		case	TRAN_REQ_DATA:		//get file
			break;
		case	TRAN_REQ_DIR:		//get directory information
			break;
		default:
			break;
		}
		break;
	case	TRAN_REQ_WRITE:			//remote request write data to local
		switch (pcmd->opcode)
		{
		case	TRAN_REQ_DATA:		//receive file
			inet_Save_File_To_Local(s, pcmd);
			break;
		default:
			break;
		}
		break;
	}
	free(pcmd);
	return RET_SUCCESS;
}


DWORD inet_Recv_Remote_Data(SOCKET sock)
{
	int buflen, ret = -1;
	PBYTE buf = NULL;
	BYTE headercnt = 0, dat = 0;
	PTF_COMMAND cmd = NULL;
	PTRAN_LIST p = net_SearchItemFromListBySocket(sock);
	ioctlsocket(sock, FIONREAD, (u_long *)&buflen);
	if (buflen > 0)
	{
		buf = malloc(buflen);
		ret = recv(sock, buf, buflen, 0);
		if (ret != buflen)
		{
			ret = RET_FAILURE | 0x01;
			free(buf);
			return ret;
		}
		ret = 0;
		cmd = malloc(sizeof(TF_COMMAND));
		INIT_CMD(cmd);
		while (ret < buflen)
		{
			dat = *(buf + ret);
			switch (headercnt)
			{
			case	0:			//command header
				if (dat == COMMAND_HEADER)
				{
					cmd->header = dat;
					headercnt ++;
				}
				break;
			case	1:			//command name
				if (INVALID_COMMAND(dat))
				{
					cmd->cmd = dat;
					headercnt ++;
				}
				else
				{
					memset(cmd, 0, sizeof(TF_COMMAND));
				}
				break;
			case	2:			//command sequence
				cmd->seq = dat;
				headercnt ++;
				break;
			case	3:			//command opcode
				cmd->opcode = dat;
				headercnt ++;
				break;
			case	4:			//command data length low byte
				cmd->low = dat;
				headercnt ++;
				break;
			case	5:			//command data length high byte
				cmd->high = dat;
				headercnt ++;
				break;
			case	6:			//command data context
				headercnt ++;
				break;
			}
			if (headercnt >= COMMAND_HEADER_LENGTH)
			{
				break;
			}
			ret ++;
		}
		if (headercnt >= COMMAND_HEADER_LENGTH)
		{
			buflen = cmd->low + (int)cmd->high * 256;
			if (buflen > 0)
			{
				cmd->data = malloc(buflen);
				memcpy(cmd->data, buf + ret, buflen);
			}
			//check the bcc of the command data context here
			ret = (int)inet_Process_Remote_Command(sock, cmd);
		}
		else
		{
			cmd->low = 1;
			cmd->high = 0;
			cmd->data = malloc(1);
			*(cmd->data) = RET_FAILURE;
			inet_Reply_Remote(sock, cmd);
		}
		free(buf);
		buf = NULL;
	}
	return (DWORD)ret;
}


DWORD inet_Write_Data(SOCKET sock)
{
	return RET_SUCCESS;
}


DWORD inet_Remote_Close(SOCKET sock)
{
	PTRAN_LIST p = net_SearchItemFromListBySocket(sock);
	net_DisposeListItemByItem(p->context);
	return RET_SUCCESS;
}


DWORD WINAPI net_Event(PNETSOCKETMESSAGE msg)
{
	DWORD ret = 0;
	switch (msg->event)
	{
		case	FD_ACCEPT:
		case	FD_CONNECT:
			ret = inet_Accept_Connect(msg->sock);
			break;
		case	FD_READ:
			ret = inet_Recv_Remote_Data(msg->sock);
			break;
		case	FD_WRITE:
			ret = inet_Write_Data(msg->sock);
			break;
		case	FD_CLOSE:
			ret = inet_Remote_Close(msg->sock);
			break;
		default:
			break;
	}
	return ret;
}





DWORD WINAPI net_Initialization(PBYTE dir, HWND hwnd, WORD port)
{
	int ret = -1;
	SOCKADDR_IN addr;
	WSAStartup(0x0101, inet_WsaData);
	inet_Local_Dir = malloc(strlen(dir) + 1);
	memset(inet_Local_Dir, 0, strlen(dir) + 1);
	memcpy(inet_Local_Dir, dir, strlen(dir));
	addr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
	addr.sin_family = AF_INET;
	addr.sin_port = htons(port);
	inet_Listen_Socket = socket(PF_INET, SOCK_STREAM, IPPROTO_IP);
	if (inet_Listen_Socket != INVALID_SOCKET)
	{
		ret = bind(inet_Listen_Socket, (struct sockaddr *)&addr, sizeof(SOCKADDR_IN));
		if (ret == 0)
		{
			ret = listen(inet_Listen_Socket, 1024);
			if (ret == 0)
			{
				ret = WSAAsyncSelect(inet_Listen_Socket, hwnd, CM_SOCKETMESSAGE, 63);
			}
		}
	}
	if (ret != 0)
	{
		closesocket(inet_Listen_Socket);
		inet_Listen_Socket = INVALID_SOCKET;
	}
	return (DWORD)ret;
}


DWORD WINAPI net_Finalization()
{
	net_RemoveList();
	if (inet_Listen_Socket != INVALID_SOCKET)
	{
		closesocket(inet_Listen_Socket);
		inet_Listen_Socket = INVALID_SOCKET;
	}
	WSACleanup();
	return RET_SUCCESS;
}


#endif	//__TRANSFER_FILE_C__

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -