一、实验目标
首先将一个图形文件划分成指定大小的数据块。在一台主机下模拟五个应用进程,其中有四个peer,分别为peer1,peer2,peer3,peer4,还有一个tracker。将上述的图片数据块按要求分配到三个节点(peer1,peer2,peer3)上,peer4从tracker上获取三个节点的数据块信息。最后从三个节点(peer1,peer2,peer3)传输图片文件的不同块到peer4上,使得该节点获取完整的图片文件。
二、实验环境
编程测试环境:软件:Dev C++ 语言:标准C语言
实验结构图:

假定peer1上存放数据块1,3,5,7
peer2上存放数据块9,10,11
peer3上存放数据块2,4,6,8
三、方案流程
实验包含以下组件:
Tracker服务器:负责记录哪些节点拥有文件的哪些部分。收到请求即发送相关信息。
节点(Peers):拥有文件的一部分,并与其他节点交换数据。也可以向Tracker服务器请求其他拥有文件部分的节点信息。
1.初始化
选择一个图片文件,并将其分割为11个小块(例如,每个块为256KB)。
设置一个Tracker服务器,并启动它。
2.创建节点(Peers)
启动4个节点,命名为peer1,peer2,peer3,peer4。
将数据块按(4,3,4)分配给Peer1,Peer2,Peer3
3.发送文件
让Peer4请求Tracker获取Peer1,Peer2,Peer3各节点上的数据块情况。从Peer1,Peer2,Peer3获取图片的数据块。得到所有数据块后拼接数据块得到完整的图片。
1 #include <windows.h>
2 #include <iostream>
3 #include <winsock.h>
4 using namespace std;
5 #define NO_FLAGS_SET 0
6 #define FILE_ID_START 1
7 #define FILE_ID_END 4
8 #define FILE_BLOCK_SIZE 409600
9 #define PORT (u_short) 44966
10 #define DEST_IP_ADDR "127.0.0.1" //Server address
11
12 INT main(VOID)
13 {
14 WSADATA Data;
15 SOCKADDR_IN destSockAddr;
16 SOCKET destSocket;
17 unsigned long destAddr;
18 int status;
19 int numsnt;
20
21 /* initialize the Windows Socket DLL */
22 status=WSAStartup(MAKEWORD(1, 1), &Data);
23 if (status != 0)
24 cerr << "ERROR: WSAStartup unsuccessful"
25 << endl;
26 /* convert IP address into in_addr form */
27 destAddr=inet_addr(DEST_IP_ADDR);
28 /* copy destAddr into sockaddr_in structure */
29 memcpy(&destSockAddr.sin_addr,
30 &destAddr, sizeof(destAddr));
31 /* specify the port portion of the address */
32 destSockAddr.sin_port=htons(PORT);
33 /* specify the address family as Internet */
34 destSockAddr.sin_family=AF_INET;
35
36 /* create a socket */
37 destSocket=socket(AF_INET, SOCK_STREAM, 0);
38 if (destSocket == INVALID_SOCKET)
39 {
40 cerr << "ERROR: socket unsuccessful" << endl;
41 status=WSACleanup();
42 if (status == SOCKET_ERROR)
43 cerr << "ERROR: WSACleanup unsuccessful"
44 << endl;
45 return(1);
46 }
47
48 cout << "Trying to connect to IP Address: "
49 << DEST_IP_ADDR << endl;
50
51 /* connect to the server */
52 status=connect(destSocket,
53 (LPSOCKADDR) &destSockAddr,
54 sizeof(destSockAddr));
55 if (status == SOCKET_ERROR)
56 {
57 cerr << "ERROR: connect unsuccessful" << endl;
58 status=closesocket(destSocket);
59 if (status == SOCKET_ERROR)
60 cerr << "ERROR: closesocket unsuccessful"
61 << endl;
62 status=WSACleanup();
63 if (status == SOCKET_ERROR)
64 cerr << "ERROR: WSACleanup unsuccessful"
65 << endl;
66 return(1);
67 }
68
69 cout << "Connected..." << endl;
70
71
72 int id = FILE_ID_START; // 文件块编号
73 FILE *fp; // 文件块读取指针
74 char fileName[100]; //文件名
75 char path[100];//路径
76 char buf[FILE_BLOCK_SIZE];
77 sprintf(fileName, "part_%02d", id);
78 while (id <= FILE_ID_END) {
79 send(destSocket, fileName, strlen(fileName) + 1, 0);// 先发送文件名
80 Sleep(50);
81 sprintf(path, "%s%s", "C:\\Users\\大梦一场\\Desktop\\peer1\\",fileName);
82 fp = fopen(path, "rb+");
83 int count = fread(buf, 1, FILE_BLOCK_SIZE, fp); // 读取全部元素
84 fclose(fp);
85 send(destSocket, buf, count, 0); // 发送文件块
86 printf("ClientPeer1 sending %s successfully\n", path);
87 Sleep(3000); // 等待 3 s
88 id++;
89 sprintf(fileName, "part_%02d", id);
90 }
91
92 }
peer4
#include <windows.h>
#include <iostream>
#include <winsock.h>
using namespace std;
#define NO_FLAGS_SET 0
#define THIS_PORT (u_short) 44967
#define PORT (u_short) 44966
#define DEST_IP_ADDR "127.0.0.1" //Server address
#define FILE_BLOCK_SIZE 409600
#define FILE_BLOCK_NUM 11
#define FILE_NAME_LEN 7
#define DEST_PORT (u_short) 44966
#define CLIENT_NUM 3
char dataBuffer[FILE_BLOCK_SIZE]; // 用于存储接收到的数据
char fileName[100]; //文件名
DWORD ThreadProc(LPVOID clientSock)
{
SOCKET NewConnection = (SOCKET)clientSock;
char dataBuffer[FILE_BLOCK_SIZE]; // 用于存储接收到的数据
char fileName[100]; //文件名
int count;
FILE *fp = NULL;
char path[100];//路径
while ((count = recv(NewConnection, dataBuffer, sizeof(dataBuffer), 0)) > 0) {
if (strlen(dataBuffer) == FILE_NAME_LEN) { // 发来的是文件名
strcpy(fileName, dataBuffer); // 记录文件名
printf("receving %s\n", fileName);
}
else {
sprintf(path, "%s%s", "C:\\Users\\大梦一场\\Desktop\\peer4\\",fileName);
fp = fopen(path, "wb"); // 创建文件
fwrite(dataBuffer, count, 1, fp);
printf("receving data %s\n", fileName);
fclose(fp);
}
}
return 0;
}
int main(void)
{
int numsnt;
char *getInfo="getInfo";
WSADATA Data;
SOCKADDR_IN serverSockAddr;
SOCKADDR_IN clientSockAddr;
SOCKET serverSock;
SOCKET clientSock;
int addrLen=sizeof(SOCKADDR_IN);
int status;
int numrcv;
char buffer[1024];
/* initialize the Windows Socket DLL */
status=WSAStartup(MAKEWORD(1, 1), &Data);
/*初始化Winsock DLL*/
if (status != 0)
cerr << "ERROR: WSAStartup unsuccessful" << endl;
/* zero the sockaddr_in structure */
memset(&serverSockAddr, 0,sizeof(serverSockAddr));
/* specify the port portion of the address */
serverSockAddr.sin_port=htons(PORT);
/* specify the address family as Internet */
serverSockAddr.sin_family=AF_INET;
/* specify that the address does not matter */
/*INADDR_ANY 的具体含义是,绑定到0.0.0.0。此时,对所有的地址都将是有效的*/
serverSockAddr.sin_addr.s_addr=htonl(INADDR_ANY);
/* create a socket */
serverSock=socket(AF_INET, SOCK_STREAM, 0);
if (serverSock == INVALID_SOCKET)
cerr << "ERROR: socket unsuccessful" << endl;
/* associate the socket with the address */
status=bind(serverSock, (LPSOCKADDR) &serverSockAddr,
sizeof(serverSockAddr));
if (status == SOCKET_ERROR)
cerr << "ERROR: bind unsuccessful" << endl;
/* allow the socket to take connections */
status=listen(serverSock, 1);
if (status == SOCKET_ERROR)
cerr << "ERROR: listen unsuccessful" << endl;
int conn=0;
while(1)
{
int clientAddrLen = sizeof(SOCKADDR); // 求出地址的长度
// 接收请求(链接客户端),第二个参数是客户端的地址
if ((clientSock = accept(serverSock, (LPSOCKADDR)&clientSockAddr, &clientAddrLen)) == INVALID_SOCKET)
{
printf("accept failed with error %d\n", WSAGetLastError());
closesocket(clientSock); // 释放客户端连接
}
// 连接客户端成功,打印客户端的ip地址和端口号
printf("当前已连接:%s:%d\n", inet_ntoa(clientSockAddr.sin_addr), ntohs(clientSockAddr.sin_port));
// 开启线程处理客户端连接
CreateThread(NULL, 0, ThreadProc, (LPVOID)clientSock, 0, NULL);
conn++;
/* 文件的拼接 */
if (conn == CLIENT_NUM) { // 接收完3个进程发送的文件
Sleep(2000);
printf("Succeeded in accepting all file blocks. \n");
int id = 1; // 文件块编号
FILE *fpr; // 文件块读取指针
FILE *fpw = fopen("C:\\Users\\大梦一场\\Desktop\\DarkSoul.jfif", "wb");
char fileName[100]; //文件名
while (id <= FILE_BLOCK_NUM) {
sprintf(fileName, "C:\\Users\\大梦一场\\Desktop\\peer4\\part_%02d", id);
fpr = fopen(fileName, "rb+");
int count = fread(dataBuffer, 1, FILE_BLOCK_SIZE, fpr);
fwrite(dataBuffer, count, 1, fpw);
id++;
fclose(fpr);
}
fclose(fpw);
Sleep(1000);
printf("DarkSoul.jfif combining succeeded!\n");
}
}
}