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

📄 receiver.cpp

📁 Visual C++模拟计算机网络中停止等待协议发送接收数据的过程
💻 CPP
字号:
// receiver.cpp : 定义控制台应用程序的入口点。
//


#include "stdafx.h"
#include <iostream>
#include <WinSock2.h>
#include "../header/ARQ.h"
#include "../header/Exception.h"

// 服务器端口
#define SERVER_PORT 2280

#pragma comment(lib,"ws2_32.lib")//设置link时的lib库


using namespace std;

SOCKET PrimaryUDP;
char FileSavePath[MAX_PATH];

void InitWinSock()
{
	WSADATA wsaData;

	if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
	{
		throw Exception("Windows sockets 2.2 startup unsuccessful");
	}
	else{
		printf("Using %s (Status: %s)\n",
			wsaData.szDescription, wsaData.szSystemStatus);
		printf("with API versions %d.%d to %d.%d\n\n",
			LOBYTE(wsaData.wVersion), HIBYTE(wsaData.wVersion),
			LOBYTE(wsaData.wHighVersion), HIBYTE(wsaData.wHighVersion));
	}
}

void mksock(int type)
{
	PrimaryUDP = socket(AF_INET, type, 0);
	if (PrimaryUDP < 0)
	{
		throw Exception("create socket error");
	}
}

void BindSock()
{
	sockaddr_in sin;
	sin.sin_addr.S_un.S_addr = INADDR_ANY;
	sin.sin_family = AF_INET;
	sin.sin_port = htons(SERVER_PORT);

	if (bind(PrimaryUDP, (struct sockaddr*)&sin, sizeof(sin)) < 0)
		throw Exception("bind error");
}

DWORD WINAPI ARecv(LPVOID lpParam)
{
	FILE * file = NULL;

	sockaddr_in remote;
	int sinlen = sizeof(remote);
	BSC buffer,bsc;
	bsc.header = STX;bsc.tail = ETX;
	memset(bsc.data, 0, MAXBSCLENGTH);
	int iread = 0;
	unsigned long dwReceived = 0;
	bool number = true;//发送方的数据开始发送时的序号设为0,为了判断是不是第一次一段数据,所以这里标为1
	while (true)
	{
		iread = recvfrom(PrimaryUDP,(char*)&buffer,sizeof(buffer),0,(sockaddr*)&remote,&sinlen);
		if (SOCKET_ERROR == iread || buffer.header != STX || buffer.tail != ETX)
		{
			//	数据错误,发送负应答
			cout<<"received a error data"<<endl;
			bsc.bcc = NAK;bsc.number=false;//number这时没有实际的意义
			sendto(PrimaryUDP,(char*)&bsc,sizeof(bsc),0,(sockaddr*)&remote,sinlen);
			continue;
		}
		if (buffer.number == number)
		{
			//	重复收到数据,发送应答消息
			cout<<"received a repeat data"<<endl;
			bsc.bcc = ACK;
			bsc.number = buffer.number;
			sendto(PrimaryUDP,(char*)&bsc,sizeof(bsc),0,(sockaddr*)&remote,sinlen);
			continue;
		}
		switch(buffer.bcc)
		{
		case ENQ:
			{
				number = !number;//准备接收下一段数据
				//	文件请求
				cout<<"received a file request message,filename:"<<buffer.data<<endl;
				//	打开文件
				if(strcmp((FileSavePath+strlen(FileSavePath)-1),"\\")!=0)
					strcat(FileSavePath,"\\");
				strcat(FileSavePath,buffer.data);
				if((file = fopen(FileSavePath, "ab")) == NULL)
				{
					cout<<"file open failed"<<endl;
					return -1;
				}
				break;
			}
		case SYN:
			{
				number = !number;
				//	文字发送中
				int i =0;
				if((i=fwrite(buffer.data, sizeof(char), sizeof(buffer.data), file)) <= 0)
				{
					cout << "write failed" << endl;
					return -1;
				}
				dwReceived += i;
				cout<<"write:"<<i<<"\treceived:"<<sizeof(buffer.data)<<endl;
				break;
			}
		case EOT:
			{
				number = !number;
				//	文件发送完毕
				cout<<"file received completely,save path:"<<FileSavePath<<",received size:"<<dwReceived<<endl;
				fclose(file);
				break;
			}
		default:
			{
				//	数据错误,发送负应答
				bsc.bcc = NAK;bsc.number=false;
				sendto(PrimaryUDP,(char*)&bsc,sizeof(bsc),0,(sockaddr*)&remote,sinlen);
				continue;
				break;
			}
			
		}
		//	发送应答消息
		bsc.bcc = ACK;
		bsc.number = buffer.number;
		sendto(PrimaryUDP,(char*)&bsc,sizeof(bsc),0,(sockaddr*)&remote,sinlen);
		

	}
	return 0;
}


int _tmain(int argc, _TCHAR* argv[])
{
	InitWinSock();			
	mksock(SOCK_DGRAM);
	BindSock();

	CreateThread(NULL, 0, ARecv, NULL, 0, NULL);

	cout<<"Please input the file save path:";
	cin>>FileSavePath;

	cout<<"receiver start succeed"<<endl;

	getchar();
	getchar();

	return 0;
}


⌨️ 快捷键说明

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