---
# System prepended metadata

title: CP

---

# CP

## h2

```cpp=
#include "header.h"

void server_threeway();
void choice();
void DNS(string);
void math(string);
void trans(string);
int detect_loss();

int server_port, server_sockfd;
string server_ip;
struct sockaddr_in server_addr, client_addr;
packet pkt_send, pkt_recv;
socklen_t addr_len;

void para()
{
	cout << "=====Parameter=====" << endl;
	cout << "RTT : " << RTT << " ms" << endl;
	cout << "threshold : " << THRESHOLD << " bytes" << endl;
	cout << "MSS : " << MSS << " bytes" << endl;
	cout << "buffer size : " << BUFFER_SIZE << " bytes" << endl;
	cout << "Server's IP is " << server_ip << endl;
	cout << "Server is listening on port " << ntohs(server_addr.sin_port) << endl;
	cout << "===============" << endl;
}

int main(int argc,char* argv[])
{
	srand(time(NULL));

	server_port = atoi(argv[1]); //字串轉數字
	server_ip = LOCAL_IP;

	para();

    server_sockfd = socket(AF_INET,SOCK_DGRAM,0);
	if (server_sockfd < 0)
	{
		cerr << "socket\n";
		exit(1);
	}

	memset(&server_addr, 0,sizeof(struct sockaddr_in));
	memset(&client_addr, 0,sizeof(struct sockaddr_in));
	server_addr.sin_family = AF_INET;
	server_addr.sin_port = htons(PORT);
	server_addr.sin_addr.s_addr = htons(INADDR_ANY);
	addr_len = sizeof(client_addr);

	if(bind(server_sockfd, (struct sockaddr*)&server_addr, sizeof(server_addr)))
	{
		cerr << "server_sockfd bind failed" <<endl;
		exit(1);
	}

	cout << "Listening for client..." << endl;
	while(1)
	{	
	    recvfrom(server_sockfd, (void*)&pkt_recv, sizeof(pkt_recv), 0, (struct sockaddr*)&client_addr, (socklen_t*)&addr_len);
		if(fork() == 0) break;
	}

    server_sockfd = socket(AF_INET,SOCK_DGRAM,0);
	server_addr.sin_port = htons(0);
	bind(server_sockfd, (struct sockaddr*)&server_addr, sizeof(server_addr));
	connect(server_sockfd ,(struct sockaddr*)&client_addr, sizeof(server_addr));

	server_threeway();
    choice();
	return 0;
}

void server_threeway()
{
	cout << "=====Start the three-way handshake=====" << endl;
    cout << "\tReceive a packet (seq_num = " << pkt_recv.seq << " , " << "ack_num = "<< pkt_recv.ack << ")" << endl;
	pkt_send = pkt_recv;
	pkt_send.checkbit[1] = 1;
	pkt_send.seq = 1 + rand() % 10000;
	pkt_send.ack = pkt_recv.seq + 1;
	sendto(server_sockfd, (void*)&pkt_send, sizeof(pkt_send), 0, (struct sockaddr*)&client_addr, addr_len);
	cout << "\tSent a packet (seq_num = " << pkt_send.seq << " ," << "ack_num = "<< pkt_send.ack << ")" << endl;

	recvfrom(server_sockfd, (void*)&pkt_recv, sizeof(pkt_recv), 0, (struct sockaddr*)&client_addr, (socklen_t*)&addr_len);
	cout << "\tReceive a packet (seq_num = " << pkt_recv.seq << " , " << "ack_num = "<< pkt_recv.ack << ")" << endl;
	cout << "=====Complete the three-way handshake=====" << endl;
}

void choice()
{
	while(1)
    {
		recvfrom(server_sockfd, (void*)&pkt_recv, sizeof(pkt_recv), 0, (struct sockaddr *)&client_addr, (socklen_t *)&addr_len);
        pkt_send.seq = pkt_recv.ack;
		pkt_send.ack = pkt_recv.seq + strlen(pkt_recv.data) + 1;
		cout << "\tReceive a packet (seq_num = " << pkt_recv.seq << " , " << "ack_num = "<< pkt_recv.ack << ")" << endl;
		
		vector<string>cmd;
		string s = pkt_recv.data;
		while(1)
        {
			int pos = s.find(' ');
			if( pos == string::npos)
            {
				cmd.push_back(s);
				cmd.back().pop_back();
				break;
			}			
			cmd.push_back(s.substr(0,pos));
			s = s.substr(pos+1);
		}
		for(int i=0; i<cmd.size(); i=i+2)
        {
			if( cmd[i] == "DNS" )
				DNS(cmd[i+1]);	
			else if (cmd[i] == "math")
				math(cmd[i+1]);
			else if (cmd[i] == "trans")
				trans(cmd[i+1]);
			}
    }
}

void DNS(string cmd)
{
	cout << "======DNS====="<<endl;
	string s = "";
	stringstream ss;
	char ip[INET6_ADDRSTRLEN];
	struct addrinfo result,*res,*p;

	memset((void*)&pkt_send, '\0', sizeof(pkt_send));
	memset(&result, 0, sizeof(result));
	result.ai_family = AF_UNSPEC;
	result.ai_socktype = SOCK_STREAM;
	
	if(getaddrinfo(cmd.c_str(), NULL, &result, &res) != 0 )
    {
		cerr << "dns error.\n";
		exit(0);
	}

	s += "IP addresses for " + cmd + ":\n";
	void *info;
	
	
	for(p=res; p!=NULL; p=p->ai_next)
    {
		void *info;
		string ipver;
		if(p->ai_family == AF_INET)
        {
			struct sockaddr_in *ipv4 = (struct sockaddr_in*)p->ai_addr;
			info = &(ipv4->sin_addr);
			ipver = "IPv4";
			inet_ntop(p->ai_family, info, ip, sizeof(ip));
			s += ipver + " : " + ip + '\n';
			break;
		}
		else
        {
			struct sockaddr_in6 *ipv6 = (struct sockaddr_in6 *)p->ai_addr;
			info = &(ipv6->sin6_addr);
			ipver = "IPv6";
		}
		inet_ntop(p->ai_family, info, ip, sizeof(ip));
		s += ipver + " : " + ip + '\n';
	}

	freeaddrinfo(res);
	pkt_send.seq = pkt_recv.ack ;
	pkt_send.ack = pkt_recv.seq + strlen(pkt_recv.data) ;
	strcpy(pkt_send.data, s.c_str());
	sendto(server_sockfd, (void*)&pkt_send, sizeof(pkt_send), 0, (struct sockaddr*)&client_addr, addr_len);
	recvfrom(server_sockfd, (void*)&pkt_recv, sizeof(pkt_recv), 0, (struct sockaddr*)&client_addr, (socklen_t *)&addr_len);
	pkt_send.seq = pkt_recv.ack ;
	pkt_send.ack = pkt_recv.seq + strlen(pkt_recv.data) + 1;
	cout << "\tReceive a packet (seq_num = " << pkt_recv.seq << " , " << "ack_num = "<< pkt_recv.ack << ")" << endl;
	cout << "=====Finish=====" << endl <<endl;
}

void math(string s)
{
	cout << "=====math====="<<endl;

	float n1,n2,ans;
	stringstream ss;
	string op;

	memset((void*)&pkt_send, '\0', sizeof(pkt_send));

	op = s.substr(0, s.find(','));
	s  = s.substr(s.find(',') + 1 );
	n1 = atof(s.substr(0, s.find(',')).c_str());
	s  = s.substr(s.find(',') + 1 );
	n2 = atof(s.c_str());

	if(op == "add")
	{
		ans = n1 + n2 ;
		op = "+";
	}
	else if(op == "sub")
	{
		ans = n1 - n2 ;
		op = "-";
	}
	else if(op == "mul")
	{
		ans = n1 * n2 ;
		op = "*";
	}
	else if(op == "div")
	{
		ans = n1 / n2 ;
		op = "/";
	}
	else if(op == "pow")
	{
		ans = pow(n1,n2);
		op = "^";
	}
	else if(op == "sqr")
	{
		ans = pow(n1, 1/n2);
	}

	s.clear();
	ss << n1;
	ss << ' ';
	ss << op;
	ss << ' ';
	ss << n2;
	ss << " = ";
	ss << ans;
	ss << endl;

	pkt_send.seq = pkt_recv.ack ;
	pkt_send.ack = pkt_recv.seq + strlen(pkt_recv.data) + 1 ;
	strcpy(pkt_send.data,ss.str().c_str());
	sendto(server_sockfd,(void*)&pkt_send, sizeof(pkt_send), 0, (struct sockaddr*)&client_addr, addr_len);
	recvfrom(server_sockfd, (void*)&pkt_recv, sizeof(pkt_recv), 0, (struct sockaddr*)&client_addr, (socklen_t*)&addr_len);
	pkt_send.seq = pkt_recv.ack;
	pkt_send.ack = pkt_recv.seq + strlen(pkt_recv.data);
	cout << "\tReceive a packet (seq_num = " << pkt_recv.seq << " , " << "ack_num = "<< pkt_recv.ack << ")" << endl;
	cout << "=====Finish=====" << endl <<endl;
}

void trans (string name)
{
	cout << "=====transmission file=====" << endl;

	char buf[MSS];
	int n;

	memset((void*)&pkt_send, '\0', sizeof(pkt_send));
	strcpy(pkt_send.data, name.c_str());
	pkt_send.seq = pkt_recv.ack ;
	pkt_send.ack = pkt_recv.seq + 1 + strlen(pkt_recv.data);
	
	cout << "\tsend a packet at : " << pkt_send.seq << " bytes\n";
	
	sendto(server_sockfd, (void*)&pkt_send, sizeof(pkt_send), 0, (struct sockaddr*)&client_addr, addr_len);
	recvfrom(server_sockfd, (void*)&pkt_recv, sizeof(pkt_recv), 0, (struct sockaddr*)&client_addr, (socklen_t*)&addr_len);
	cout << "\tReceive a packet (seq_num = " << pkt_recv.seq << " , " << "ack_num = "<< pkt_recv.ack << ")" << endl;
	
	memset(buf, '\0', sizeof(buf));
	memset((void*)&pkt_send, '\0', sizeof(pkt_send));

	FILE *f = fopen(name.c_str(), "rb");
	while((n = fread(pkt_send.data, 1, sizeof(pkt_send.data), f)) > 0)
	{
		memset(buf, '\0', sizeof(pkt_send.data));
		pkt_send.datalen = n;
		pkt_send.seq = pkt_recv.ack ;
		pkt_send.ack = pkt_recv.seq + 1 + pkt_recv.datalen;

		int loss_flag = detect_loss();

		if(loss_flag == 1)
			cout << "detect loss at " << pkt_send.seq << "byte" << endl;
		else
			cout << "\tsend a packet at : " << pkt_send.seq << " bytes\n";
		
		sendto(server_sockfd, (void*)&pkt_send, sizeof(pkt_send), 0, (struct sockaddr *)&client_addr, addr_len);
		recvfrom(server_sockfd, (void*)&pkt_recv, sizeof(pkt_recv), 0, (struct sockaddr *)&client_addr, (socklen_t *)&addr_len);
		
		if(loss_flag != 1)
		cout << "\tReceive a packet (seq_num = " << pkt_recv.seq << " , " << "ack_num = "<< pkt_recv.ack << ")" << endl;
		
		memset(buf, '\0', sizeof(buf));
		memset((void*)&pkt_send, '\0', sizeof(pkt_send));
		memset(pkt_send.data, '\0', sizeof(pkt_send.data));
	}

	fclose(f);

	memset(buf, '\0', sizeof(buf));
	memset((void*)&pkt_send, '\0', sizeof(pkt_send));

	pkt_send.fin = 1;
	pkt_send.seq = pkt_recv.ack ;
	pkt_send.ack = pkt_recv.seq + 1 + strlen(pkt_recv.data);
	
	sendto(server_sockfd, (void*)&pkt_send, sizeof(pkt_send), 0, (struct sockaddr *)&client_addr, addr_len);
	cout << "=====Finish=====" << endl <<endl;
}

int detect_loss()
{
	random_device rd;
    	mt19937 gen(rd());
	poisson_distribution<> d(0.1);
	if(d(gen) > 0) return 1;
	else return 2;
}
```


```cpp!=
#include "header.h"

int client_threeway(void);
int request(void);

int client_sockfd, port;
string address;
struct sockaddr_in addr;
packet pkt_recv,pkt_send;
socklen_t addr_len;

int main(int argc,char* argv[])
{
	string IP;
	int send_port;
    
	if(argc == 1)
    {
		//IP = "0.0.0.0";
	    //send_port = PORT;
        cin >> IP >> send_port;
        cin.clear();
        cin.ignore(numeric_limits<streamsize>::max(), '\n');
	}
	else if(argc == 3)
    {
		IP = argv[1];
		send_port = atoi(argv[2]);
	}

    address = IP;
    port = send_port;
    if((client_sockfd = socket(AF_INET, SOCK_DGRAM, 0)) <0)
    {
        cerr << "socket\n";
        exit(1);
    }
	memset(&addr, 0, sizeof(addr));  
	addr.sin_family = AF_INET;
	addr.sin_addr.s_addr = inet_addr(address.c_str());
    // big to little endian
	addr.sin_port = htons(port);
    addr_len = sizeof(addr);
    
    memset(&pkt_send, 0, sizeof(packet));
    memset(&pkt_recv, 0, sizeof(packet));

	while(1)
		if(client_threeway())
            break;
	request();
}
int getsize(char *ptr) {
    int i = 0;
    while(ptr[i] != '\0')
        ++i;
    return i;
}
int client_threeway()
{
    cout << "=====start the three-way handshake=====\n";
    srand(time(NULL));
    pkt_send.seq = 1 + rand()%10000;
    pkt_send.checkbit[0] = 1;
    sendto(client_sockfd, (void*)&pkt_send, sizeof(pkt_send), 0, (struct sockaddr*)&addr, addr_len);
    cout << "Send a packet(SYN) to " << address << " : " << port << endl;
    cout << "\tpacket(seq) : " << pkt_send.seq << endl;
    cout << "\tSend a packet at : " << sizeof(pkt_send) << " byte\n";
    recvfrom(client_sockfd, (void*)&pkt_recv, sizeof(pkt_recv), 0, (struct sockaddr*)&addr, (socklen_t*)&addr_len);
    if(pkt_recv.checkbit[0] != 1 || pkt_recv.checkbit[1] != 1 )
    {
        cerr << "connect (three way)\n";
        return 0;
    }
    pkt_send.ack = pkt_recv.seq + 1 ;
    ++pkt_send.seq ;
    cout << "Receive a packet(SYN/ACK) from " << address << " : " << port << endl;
    cout << "\tReceive a packet (seq_num = " << pkt_recv.seq << ",ack_num = " << pkt_recv.ack <<" )" << endl;
    sendto(client_sockfd, (void*)&pkt_send, sizeof(pkt_send), 0, (struct sockaddr *)&addr, addr_len);
    cout << "Send a packet to " << address << " : " << port << endl;
    cout << "\tSend a packet at : " << sizeof(pkt_send)<< " byte\n";
    cout << "=====complete the three-way handshake=====\n";
    return 1;
}

int request(void)
{
    while(1)
    {
        memset((void*)&pkt_send, 0, sizeof(pkt_send));
        cout << "input request (DNS/math/trans)" << endl;
        cin.ignore(0);
        fgets(pkt_send.data, MSS, stdin);
       
        string s = pkt_send.data;
        pkt_send.ack = 0;
        pkt_send.request = 1;
        sendto(client_sockfd, (void*)&pkt_send, sizeof(pkt_send), 0, (struct sockaddr*)&addr, addr_len);
        cout << "send a packet : " << strlen(pkt_send.data)+36 << "byte \n";
        //cout << "send a packet : " << sizeof(pkt_send.data) << '\n';
        memset((char*)&pkt_send, 0, sizeof(pkt_send));

        vector<string>cmd;
        while(1)
        {
            int pos = s.find(' ');
            if(pos == string::npos)
            {
                cmd.push_back(s);
                cmd.back().pop_back();
                break;
            }			
            cmd.push_back(s.substr(0,pos));
            s = s.substr(pos+1);
        }
        for(int i=0; i<cmd.size(); i=i+2)
        {
            memset((void*)&pkt_send, 0, sizeof(pkt_send));
            if(cmd[i]=="DNS"||cmd[i]=="math" )
            {
                recvfrom(client_sockfd, (void*)&pkt_recv, sizeof(pkt_recv), 0, (struct sockaddr*)&addr, (socklen_t*)&addr_len);
                cout << "\tReceive a packet (seq_num = " << pkt_recv.seq << " ),(" << "ack_num = "<< pkt_recv.ack << ")" << endl;
                pkt_send.seq = pkt_recv.ack ;
                pkt_send.ack = pkt_recv.seq + strlen(pkt_recv.data) + 1;
                pkt_send.request = 0;
                sendto(client_sockfd, (void*)&pkt_send, sizeof(pkt_send), 0, (struct sockaddr *)&addr, addr_len);
                char tmp[INET_ADDRSTRLEN];
                inet_ntop(AF_INET, &(addr.sin_addr), tmp, INET_ADDRSTRLEN);
                cout << "Send a packet(ACK) to " << tmp << " : " << ntohs(addr.sin_port) << "\n";
                cout << "\tSend a packet at : " << sizeof(pkt_send) << " byte\n";
                cout << pkt_recv.data << endl;
            }
            else if(cmd[i] == "trans")
            {
                recvfrom(client_sockfd, (void*)&pkt_recv, sizeof(pkt_recv), 0, (struct sockaddr*)&addr, (socklen_t*)&addr_len);
                cout << "\tReceive a packet (seq_num = " << pkt_recv.seq << " ),(" << "ack_num = "<< pkt_recv.ack << ")" << endl;
                pkt_send.seq = pkt_recv.ack ;
                pkt_send.ack = pkt_recv.seq + strlen(pkt_recv.data) + 1;
                pkt_send.request = 0;
                sendto(client_sockfd, (void*)&pkt_send, sizeof(pkt_send), 0, (struct sockaddr*)&addr, addr_len);
                string filename = pkt_recv.data;
                cout << "Receiving file : " << filename << "...." << endl;
                FILE *f = fopen(("test/" + filename).c_str(),"wb");
                while(recvfrom(client_sockfd, (void*)&pkt_recv, sizeof(pkt_recv), 0, (struct sockaddr*)&addr, (socklen_t *)&addr_len))
                {
                    if(pkt_recv.fin == 1)break;
                    
                    pkt_send.datalen = 0;
                    pkt_send.seq = pkt_recv.ack ;
                    pkt_send.ack = pkt_recv.seq + pkt_recv.datalen;
                    pkt_send.request = 0;
                    cout << "\tReceive a packet (seq_num = " << pkt_recv.seq << " ),(" << "ack_num = "<< pkt_recv.ack << ")" << endl;
                    fwrite(pkt_recv.data,1,pkt_recv.datalen,f);
                    sendto(client_sockfd, (void*)&pkt_send, sizeof(pkt_send), 0, (struct sockaddr*)&addr, addr_len);

                }
                cout << "file accecpt : " << filename << endl <<endl;
                fclose(f);
            }
        }
    }
    return 1;
}

```