# 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;
}
```