Demo entry 6659201

mid_server

   

Submitted by anonymous on Nov 10, 2017 at 06:30
Language: C++. Code size: 6.8 kB.

/* Select Server */
#include <iostream>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <arpa/inet.h>
#include <cstring>
#include <unistd.h>
#include <errno.h>
#include <vector>
#define MAXLINE 1024
#define LISTENQ 1024

using namespace std;

class client {
public:
	char id[16];
	int sockfd;
	char ip[32];
	int port;
	vector<string> filelist;
	client(int _sockfd, char _ip[32], int _port) {
		init(_sockfd, _ip, _port);
	}
	void init(int _sockfd=-1, char _ip[32]="", int _port=0) {
		bzero(id, 16);
		sockfd = _sockfd;
		strcpy(ip, _ip);
		port = _port;
		filelist.clear();
	}
	void info() {
		cout << sockfd << ' ' << ip << '/' << port << endl;
	}
	void set_id(char _id[16]) {
		strcpy(id, _id);
	}
	bool id_exist() {
		if (strlen(id)) return true;
		return false;
	}
};

fd_set allset;
vector<client> user;
int SERV_PORT = 7777;

int Listen(int &listenfd, int &port) {
	struct sockaddr_in servaddr;

	listenfd = socket(AF_INET, SOCK_STREAM, 0);

	bzero(&servaddr, sizeof(servaddr));
	servaddr.sin_family = AF_INET;
	servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
	servaddr.sin_port = htons(port);

	while ( bind(listenfd, (struct sockaddr*)&servaddr, sizeof(servaddr)) < 0) {
		port = rand() % 30000 + 10000;
		servaddr.sin_port = htons(port);
	}

	listen(listenfd, LISTENQ);

	cout << "Server is at port " << port << endl;

	return listenfd;
}

int Connect(int &listenfd) {
	struct sockaddr_in cliaddr;
	socklen_t clilen;

	clilen = sizeof(cliaddr);
	int connfd = accept(listenfd, (struct sockaddr*)&cliaddr, &clilen);

	user.push_back(client(connfd, inet_ntoa(cliaddr.sin_addr), ntohs(cliaddr.sin_port)));
	user.back().info();

	if (user.size() == FD_SETSIZE) cerr << "too many clients" << endl;
	FD_SET(connfd, &allset);

	return connfd;
}

void Disconnect(int i) {
	cout << "Disconnect " << user[i].sockfd << endl;
	close(user[i].sockfd);
	FD_CLR(user[i].sockfd, &allset);
	user[i].sockfd = -1;
}


void Echo(int i, char line[MAXLINE]) {
	write(user[i].sockfd, line, strlen(line));
}

void Upload(int i, char file1[MAXLINE], char filename[MAXLINE]) {
	char filepath[MAXLINE];

	sprintf(filepath, "file/%s", user[i].id);
	mkdir(filepath, 0755);

	sprintf(filepath, "file/%s/%s", user[i].id, filename);
	int file = open(filepath, O_RDWR | O_CREAT, 0644);
	user[i].filelist.push_back(string(filename));

	int listenfd;
	int port = rand() % 30000 + 10000;
	Listen(listenfd, port);

	char sendline[MAXLINE];
	int n = sprintf(sendline, "PUT %d %s\n", port, file1);
	write(user[i].sockfd, sendline, n);

	while (true) {
		fd_set rset;
		FD_ZERO(&rset);
		FD_SET(listenfd, &rset);
		if (FD_ISSET(listenfd, &rset)) {
			int filefd = Connect(listenfd);
			FD_SET(filefd, &rset);
			while (true) {
				fd_set fset = rset;
				if (FD_ISSET(filefd, &fset)) {
					int n;
					char recvline[MAXLINE];
					bzero(recvline, MAXLINE);
					if ((n = read(filefd, recvline, MAXLINE)) == 0) {
						Disconnect(user.size() - 1);
						user.erase(user.end() - 1);
						close(file);
						return;
					}
					else {
						write(file, recvline, n);
					}
				}
			}
		}
	}
}

bool Download(int i, char file2[MAXLINE], char filename[MAXLINE]) {
	char filepath[MAXLINE];
	sprintf(filepath, "file/%s/%s", user[i].id, filename);
	int file = open(filepath, O_RDONLY);
	if (file < 0) return false;
	int listenfd;
	int port = rand() % 30000 + 10000;
	Listen(listenfd, port);

	char sendline[MAXLINE];
	int n = sprintf(sendline, "GET %d %s\n", port, file2);
	write(user[i].sockfd, sendline, n);

	while (true) {
		fd_set rset;
		FD_ZERO(&rset);
		FD_SET(listenfd, &rset);
		if (FD_ISSET(listenfd, &rset)) {
			int filefd = Connect(listenfd);
			int n;
			char sendline[MAXLINE];
			bzero(sendline, MAXLINE);
			while (n = read(file, sendline, MAXLINE)) {
				write(filefd, sendline, n);
			}
			Disconnect(user.size() - 1);
			user.erase(user.end() - 1);
			close(file);
			return true;
		}
	}
}

void Cloud(int i, char recvline[MAXLINE]) {
	int n;
	char cmd[MAXLINE], params1[MAXLINE], params2[MAXLINE];
	char sendline[MAXLINE];
	bzero(sendline, MAXLINE);
	sscanf(recvline, "%s %s %s", cmd, params1, params2);
	if (strcmp(cmd, "CLIENTID:") == 0) {
		if (strlen(params1) != 5) {
			Echo(i, "CMD Client ID must be 5 digits\n");
			return;
		}
		for (int i = 0; params1[i]; i++) {
			if (!isdigit(params1[i])) {
				Echo(i, "CMD Client ID must be 5 digits\n");
				return;
			}
		}
		user[i].set_id(params1);
		for (int j = 0; j < user.size(); j++) {
			if (i != j && strcmp(user[j].id, params1) == 0) {
				user[i].filelist = user[j].filelist;
				user.erase(user.begin() + j);
				break;
			}
		}
		Echo(i, "CMD ID setting succeeded\n");
		return;
	}
	if (!user[i].id_exist()) {
		Echo(i, "CMD Please set your client id first\nCLIENTID: <ID>\n");
		return;
	}
	if (strcmp(cmd, "PUT") == 0) {
		if (strlen(params1) == 0 || strlen(params2) == 0) {
			sprintf(sendline, "CMD Error Command.\n");
			write(user[i].sockfd, sendline, strlen(sendline));
		}

		Upload(i, params1, params2);

		n = sprintf(sendline, "CMD PUT %s %s succeeded\n", params1, params2);
		write(user[i].sockfd, sendline, n);
	}
	else if (strcmp(cmd, "GET") == 0) {
		if (strlen(params1) == 0 || strlen(params2) == 0) {
			sprintf(sendline, "CMD Error Command.\n");
			write(user[i].sockfd, sendline, strlen(sendline));
		}
		if (Download(i, params2, params1)) {
			n = sprintf(sendline, "CMD GET %s %s succeeded\n", params1, params2);
			write(user[i].sockfd, sendline, n);
		}
		else {
			n = sprintf(sendline, "CMD GET %s %s failed\n", params1, params2);
			write(user[i].sockfd, sendline, n);
		}

	}
	else if (strcmp(cmd, "LIST") == 0) {
		strcpy(sendline, "CMD ");
		for (auto f : user[i].filelist) {
			strcat(sendline, f.c_str());
			strcat(sendline, "\n");
		}
		strcat(sendline, "LIST succeeded\n");
		write(user[i].sockfd, sendline, strlen(sendline));
	}
	else {
		sprintf(sendline, "CMD Error Command.\n");
		write(user[i].sockfd, sendline, strlen(sendline));
	}
}

void Service(int i) {
	char recvline[MAXLINE];
	bzero(recvline, MAXLINE);
	if (read(user[i].sockfd, recvline, MAXLINE) == 0) {
		Disconnect(i);
	}
	else {
		Cloud(i, recvline);
	}
}

void Select_Server(int &listenfd) {
	int maxfd = listenfd;
	while (true) {
		fd_set rset = allset;
		int nready = select(maxfd+1, &rset, NULL, NULL, NULL);

		if (FD_ISSET(listenfd, &rset)) {
			maxfd = max(maxfd, Connect(listenfd));
			nready--;
		}

		for (int i = 0; i < user.size() && nready; i++) {
			if (FD_ISSET(user[i].sockfd, &rset)) {
				Service(i);
				nready--;
			}
		}
	}
}

int main(int argc, const char *argv[])
{
	if (argc == 2) SERV_PORT = atoi(argv[1]);

	mkdir("file", 0755);

	int listenfd;
	Listen(listenfd, SERV_PORT);

	FD_ZERO(&allset);
	FD_SET(listenfd, &allset);

	Select_Server(listenfd);

	return 0;
}

This snippet took 0.03 seconds to highlight.

Back to the Entry List or Home.

Delete this entry (admin only).