您的位置:首页 > 理论基础 > 计算机网络

一个简单的在本地传输文件的网络程序

2012-11-16 13:48 477 查看
经常在CSDN贴吧看见很多关于网络之间传输的例子(比如传输截屏文件),所以很想写一个作为学习。

此程序设定很简单,就是在本地传输。当然,要扩展到网络也很简单,改个ip就ok了。

基本思路:

双方遵循一个包头格式,根据包头确定之后的操作。

服务器代码:

#include <string>
#include <io.h>

#define PORT 6666

struct PacketHeader
{
	char code[10];		// 指令:"EOF"=断开连接  "PIC"=接收图片
	char name[50];		// 名字:包括后缀
	LONG32 size;		// 大小:字节
	PacketHeader()
	{
		memset(code,0,sizeof(code));
		memset(name,0,sizeof(name));
		size = 0;
	}
};

// 在本地传输图片
void server()
{
	WSADATA wd;
	int ret = WSAStartup(MAKEWORD(2,2),&wd);
	if(ret != 0)
	{
		cout<<"Initialize Winsock Failed! "<<GetLastError()<<endl;;
		return;
	}
	cout<<"WSAStartup OK"<<endl;

	sockaddr_in addr_serv,addr_cli;
	int sock_listen,sock_accept;
	try{
		sock_listen = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
		if(sock_listen == SOCKET_ERROR)
		{
			cout<<"create socket failed! "<<GetLastError()<<endl;
			throw 1;
		}
		cout<<"socket OK"<<endl;

		memset((void*)&addr_serv,0,sizeof(sockaddr));
		addr_serv.sin_family = AF_INET;
		addr_serv.sin_addr.S_un.S_addr = INADDR_ANY;
		addr_serv.sin_port = htons(PORT);

		ret = bind(sock_listen,(sockaddr*)&addr_serv,sizeof(addr_serv));
		if(ret != 0)
		{
			cout<<"bind failed! "<<GetLastError()<<endl;
			throw 2;
		}
		cout<<"bind OK"<<endl;

		ret = listen(sock_listen,1);
		if(ret != 0)
		{
			cout<<"listen failed! "<<GetLastError()<<endl;
			throw 2;
		}
		cout<<"listen OK"<<endl;

		int addrlen = sizeof(addr_cli);
		sock_accept = accept(sock_listen,(sockaddr*)&addr_cli,&addrlen);
		if(sock_accept == INVALID_SOCKET)
		{
			cout<<"accept failed! "<<GetLastError()<<endl;
			throw 2;
		}
		cout<<"accept OK"<<endl;
		closesocket(sock_listen);	//停止监听

		while(true)
		{
			cout<<"输入:(EOF表示断开连接,文件名表示发送文件,例如sumos.txt)"<<endl;
			string input;
			cin>>input;
			if(input.compare("EOF") == 0)
			{
				PacketHeader ph;
				strcpy_s(ph.code,"EOF");
				send(sock_accept,(const char*)&ph,sizeof(ph),0);
				break;
			}
			else 
			{
				FILE* fp = NULL;
				fopen_s(&fp,input.c_str(),"rb");
				if(fp == NULL)
				{
					cout<<"打开失败"<<endl;
					continue;
				}
				else
				{
					LONG32 sz = _filelength(_fileno(fp));
					cout<<"文件打开成功,大小:"<<sz<<" Bytes"<<endl;
					PacketHeader ph;
					strcpy_s(ph.code,"PIC");
					strcpy_s(ph.name,input.c_str());
					ph.size = sz;
					send(sock_accept,(const char*)&ph,sizeof(ph),0);
					cout<<"已发送头部信息"<<endl;

					int nSend = 0;
					char buffer[1024];
					while(nSend < sz)
					{
						int nBytes = fread(buffer,sizeof(char),1024,fp);
						if(nBytes <= 0)							
							break;					
						send(sock_accept,buffer,nBytes,0);
						cout<<"已发送 "<<nBytes<<" Bytes"<<endl;
						nSend += nBytes;
					}
					cout<<"总计发送 "<<nSend<<" Bytes"<<endl;
					fclose(fp);
				}
			}
		}
		closesocket(sock_accept);
	}catch(int which){
		if(which == 2)
			closesocket(sock_listen);
		if(which == 3)
			closesocket(sock_accept);
	}
	WSACleanup();
}

客户端代码:

#include <WinSock.h>
#pragma comment(lib,"ws2_32.lib")

#define IP		"127.0.0.1"
#define PORT	6666

struct PacketHeader
{
	char code[10];		// 指令:"EOF"=断开连接  "PIC"=接收图片
	char name[50];		// 名字:包括后缀
	LONG32 size;		// 大小:字节
	PacketHeader()
	{
		memset(code,0,sizeof(code));
		memset(name,0,sizeof(name));
		size = 0;
	}
};

void client() 
{
	WSADATA wd;
	int ret = WSAStartup(MAKEWORD(2,2),&wd);
	if(ret != 0)
	{
		cout<<"Initialize Winsock Failed! "<<GetLastError()<<endl;;
		return;
	}
	cout<<"WSAStartup OK"<<endl;

	sockaddr_in addr_serv;
	int sock;
	try{
		sock = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
		if(sock == SOCKET_ERROR)
		{
			cout<<"create socket failed! "<<GetLastError()<<endl;
			throw 1;
		}
		cout<<"socket OK"<<endl;

		memset((void*)&addr_serv,0,sizeof(sockaddr));
		addr_serv.sin_family = AF_INET;
		addr_serv.sin_addr.S_un.S_addr = inet_addr(IP);
		addr_serv.sin_port = htons(PORT);

		ret = connect(sock,(sockaddr*)&addr_serv,sizeof(addr_serv));
		if(ret == SOCKET_ERROR)
		{
			cout<<"connect failed! "<<GetLastError()<<endl;
			throw 2;
		}
		cout<<"connect OK"<<endl;

		char buffer[1024];
		while(true)
		{
			int nRecv = recv(sock,buffer,1024,0);
			if(nRecv <= 0)
				continue;
			else if(nRecv == sizeof(PacketHeader))
			{
				PacketHeader ph;
				memcpy_s(&ph,sizeof(ph),buffer,nRecv);
				if(strcmp(ph.code,"EOF") == 0)
					break;
				else if(strcmp(ph.code,"PIC") == 0)
				{
					cout<<"文件名:"<<ph.name<<",大小:"<<ph.size<<endl;
					FILE* fp = NULL;
					fopen_s(&fp,ph.name,"wb");
					if(fp == NULL)
					{
						cout<<"创建文件失败"<<endl;
						break;
					}
					else
					{
						nRecv = 0;
						while(nRecv < ph.size)
						{
							int nBytes = recv(sock,buffer,1024,0);
							if(nBytes <= 0)
								break;
							cout<<"已接收 "<<nBytes<<" Bytes"<<endl;
							fwrite(buffer,sizeof(char),nBytes,fp);
							nRecv += nBytes;
						}
						cout<<"共接收 "<<nRecv<<" Bytes"<<endl;
						fclose(fp);
					}
				}
				else
				{
					cout<<"头部信息错误"<<endl;
					break;
				}
			}
			else
			{
				buffer[nRecv] = '\0';
				cout<<buffer<<endl;
			}
		}
		closesocket(sock);
	}catch(int which){	
		if(which == 2)
		closesocket(sock);
	}
	WSACleanup();
}

运行截图:

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐