Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

pythonclient #1

Open
wants to merge 5 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 24 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,32 @@

## Team Members
- team member 1
Charlie Welland
- team member 2
Charlotte Kroll

## Lab Question Answers

Answer for Question 1:
Question 1: How did the reliability of UDP change when you added 50% loss to
your local environment? Why did this occur?

...
The realiability of the UDP changed when I added the %50 loss to the
local environment. It seemed like half of the packages failed to come through.

Question 2: How did the reliability of TCP change? Why did this occur?

While we told the reliability of TCP to change by %50 for the worse, the packages
still seemed to come through. This is do to the TCP system checking to see if
packages were delivered. If they are not, it will send them again. This is
different than UDP because if a package is not delivered in UDP, it's tough
luck. Due to this TCP protocol, the packages will still get delivered even
after calling
sudo tc qdisc add dev lo parent root netem loss 50%

Question 3: How did the speed of the TCP response change? Why might this happen?

The speed of the TCP response slowed significantly. This was due to the TCP
process putting the server in time out while it still made sure all
previous packages were received. If the packages were not being received on
first attempt, the system would wait till the package was eventually recieved.
This caused the system to slow substantially.
18 changes: 13 additions & 5 deletions tcp_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,19 @@
import socket

def main():
# TODO: Create a socket and connect it to the server at the designated IP and port
HOST = "localhost"
PORT = 19000
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.connect((HOST,PORT))
message = str(input("Enter a message: "))
s.sendall(message.encode("utf-8"))
data = s.recv(1024)
s.close()
decoded = data.decode("utf-8")
print(f"Received {decoded!r}")

# TODO: Create a socket and connect it to the server at the designated IP and port
# TODO: Get user input and send it to the server using your TCP socket
# TODO: Receive a response from the server and close the TCP connection
pass


if __name__ == '__main__':
main()
main()
45 changes: 35 additions & 10 deletions tcp_server.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,17 +18,25 @@ void error(const char *msg)
int main(int argc, char *argv[])
{
/* 1. What is argc and *argv[]?
*
argc and argv[] are ways for the main() function to interact and get commands from
the command line. argc contains the amount of arguments are being passes while
*argv[] is an array of pointers to the arguments being passed.
*/
int sockfd, newsockfd, portno;
/* 2. What is a UNIX file descriptor and file descriptor table?
*
A file descriptor is a single integer that contains information to identify an
open file. A file descriptor table is just a collection of these file descriptor
so that the operating system can access this information.
*/
socklen_t clilen;

struct sockaddr_in serv_addr, cli_addr;
/* 3. What is a struct? What's the structure of sockaddr_in?
*
A stuct is a data type that is a collection of other data types. Its essentially
a big block of smaller nuggest of information. A struct commonly has data types such as
strings or ints but it can also be a collection of other structs or classes. Here,
serv_addr and cli_addr are just instances of the struct sockaddr_in. Together the
struct stores internet addresses.
*/

int n;
Expand All @@ -39,7 +47,10 @@ int main(int argc, char *argv[])

sockfd = socket(AF_INET, SOCK_STREAM, 0);
/* 4. What are the input parameters and return value of socket()
*
AF_INET tells the socket what address family to talk to. Here, AF_INET tells the socket to use IPv4.
sock stream tells the function the socket type being used. Here, it is telling the function that the
TCP protocol is being used. Finally, 0 tells the socket function to use the default protocol for
SOCK_STREAM. The return value of socket() is just a file descriptor.
*/

if (sockfd < 0)
Expand All @@ -54,23 +65,36 @@ int main(int argc, char *argv[])
sizeof(serv_addr)) < 0)
error("ERROR on binding");
/* 5. What are the input parameters of bind() and listen()?
*
The first input parameter of bind() is sockfd. It is a socket descriptor which tells the function the socket’s endpoint.
Next is (struct sockaddr *) &serv_addr, it is a pointer that has the server's address information. Last is sizeof(serv_addr) 
it represents the size of sockaddr. listen() has two input parameters. The first is sockfd, a socket descriptor that tells
the function that this is a passive socket so it receives connection requests. Lastly, we have backlog. It contains the
largest number of connections that can possibly be waiting for the socket.
*/

listen(sockfd,5);
clilen = sizeof(cli_addr);

while(1) {
/* 6. Why use while(1)? Based on the code below, what problems might occur if there are multiple simultaneous connections to handle?
*
The while loop to make sure the program always iterates through the while loop to make sure it it always ready to
recieve new addresses. The issue is with this is if it is running through the while loop accepting one new address,
an even newer address could be missed.
*/

char buffer[256];
newsockfd = accept(sockfd,
(struct sockaddr *) &cli_addr,
&clilen);
/* 7. Research how the command fork() works. How can it be applied here to better handle multiple connections?
*
The fork() command is a way to create a new process in Unix-like operating systems by copying the current one.
The new process is called a "child process" and it's a complete copy of the "parent process," including its program,
memory, and information about what it's doing. The child process runs on its own and can do different things from the
parent process. The fork() command returns a special number to let the parent and child know who's who. The child
process can then change what it's running using the exec() command. It can be used to handle multiple client connections
in a TCP client-server system simultaneously. The server creates a child process for each incoming connection, allowing
the parent process to keep listening for new connections. This way, multiple clients can be served efficiently without
blocking other clients.
*/

if (newsockfd < 0)
Expand All @@ -80,7 +104,7 @@ int main(int argc, char *argv[])
n = read(newsockfd,buffer,255);
if (n < 0)
error("ERROR reading from socket");
//printf("Here is the message: %s\n",buffer);
printf("Here is the message: %s\n",buffer);
n = write(newsockfd,"I got your message",18);
if (n < 0)
error("ERROR writing to socket");
Expand All @@ -91,5 +115,6 @@ int main(int argc, char *argv[])
}

/* This program makes several system calls such as 'bind', and 'listen.' What exactly is a system call?
*
*/
A system call is just a way for the user to request some sort of service that is ran by the operating system.
These inlcude read(), write(), fork(), etc.
*/