Answered step by step
Verified Expert Solution
Link Copied!

Question

1 Approved Answer

Program 2 Specifications Name your source code files WSEchoServerv6.c and ProcessClient.c . Use the DisplayFatalErr.c module from Program 1 to handle errors. Use your own

Program 2 Specifications

Name your source code files WSEchoServerv6.c and ProcessClient.c. Use the DisplayFatalErr.c module from Program 1 to handle errors. Use your own WSEchoClientv6.exe(Program 1) to test your server. This program will be implemented as a command line program in C. It will obtain its input data from one command line argument, as follows:

WSEchoServerv6

For example: WSEchoServerv6 5000

You may design your server to use a default port number if none is provided as a command line argument. When starting your server, use a port number above the range of well-known port numbers (1 1024).

All network communication will be achieved using the Windows Sockets API. Do not use C++ socket classes.

Include the program number, and your name, section, date, Windows version and Visual Studio version in the program header comments.

Include the header(.h) files required to support Windows Sockets.

Use C or C++ style comments to document each call to the WinSock API. Refer toProgramming Assignments/Program 1/style.pdfin Canvas for style guidelines.

Feel free to insert additional printf() and getchar()statements into your server code for debugging purposes, but you must remove them and recompile before submitting your program to Canvas, so that the grader doesnt have to press ENTER repeatedly to get your server to accept a client connection and echo the message. Failing to do this may lower your score.

Code the following required procedural activities in the order listed.

1.The primary source code file will be named WSEchoServerv6.c. This will contain your main()function. As with your client, verify the correct number of command line arguments have been provided by the user. You dont need to validate the content of those arguments.If no port number is included on the command line, you may use a default port of your own choosing.

2. Initialize the WinSock DLL.After a successful call to WSAStartup(), handle any errors by callingDisplayFatalErr().

3.Create the server socket.

4.Load the server information into the servers sockaddr_in6structure (see Lecture 12 slide titled Server Socket Initialization). Use in6addr_anyas the servers IP address.

5.bind()the server socket tothissockaddr_in6structure.

6.Call listen() to tell the server the maximum simultaneous client connection requests to allow.

7.Display a message on the server console that includes your initials, similar to this:JD's IPv6 echo server is ready for client connection...

8.Enter a forever loop like this:for (;;){...}From within this loop, call accept()and wait for a client connection. Calling accept() from within this for loop will allow the server to accept connection requests from one or more clients, but only one at a time. Echo back one complete client message per connection request. (This non-threaded program will not support multiple simultaneous client connections.)

9.Each time a client connects to the server in this loop, display the IP address and port number of the client, and the servers own port number (from the servers sockaddr_in6) on the servers console, as shown below:

Processing the client at , clientport , server port

For example: Processing the client at ::1, client port 54321, server port 5000

Use inet_ntop()to convert an IP address from network format into a text string suitable for display(as shown above). Use ntohs()to convert a 16-bit port number from network format back into a 16-bit Windows integer.Verify that both port numbers are displayed as numerically correct values (not reversed).

10. From within the foreverloop, call a function named ProcesClient()to receive the message from your client. Implement ProcesClient() in a separate source code file named ProcessClient.c. Declare ProcessClient() in WSEchoServerv6.c, outside of main(), the same way that DisplayFatalError()is declared. Check for errors in theSockets receive process, as indicated by a negative return value from recv().

11.Echo the message back to the client from within ProcessClient(). Be sure that all of the clients message has been received and echoed by the server.You cant count bytes as you did with the client, because the server doesnt know in advance how many bytes to expect from the client, and whether all of those bytes will be received in the initial call to recv(). So call recv() repeatedly until recv()returns message length 0, indicating that the client has closed the connection. (See the Lecture 11 slide titled recv( ) for details.)

12.While still inProcessClient(), close the client socket, return to the forever loop in WSEchoServerv6.c, then call accept()and wait for another client connection.

13.While waiting in the forever loop for client communication, the server can be terminated with CTRL+C. No special programming is required to enable this. Note that CTRL+C works when running the server from the command line, but not if you are running it in the Visual Studio debugger.Because we are using this crude termination mechanism for the server, no call to closesocket() will be needed to close the server socket and no call toWSACleanup()will be needed to release the WinSock DLL resources. Those functions will be handled by the operating system. (In a real sockets program, omitting closesocket() and WSACleanup() would be considered poor design.)

Testing Your Echo Server

Design and code your echo server, build the solution and debug any compiler errors. After your program compiles successfully, test it with your client in loopback mode, running both programs from the command line. Start the server first, like this: WSEchoServerv6In a second command line window, run the client like this:

WSEchoClientv6::1 <"Messageto echo">

Verify that your server echoes the message back to your client, and that the client can reconnect and echo another message while the server continues running.If not, debug the server.

WSEchoClientv6.c

// Minimum required header files for C Winsock program #include // for print functions #include // for exit() #include // for Winsock2 functions #include // adds support for getaddrinfo & getnameinfo for v4+6 name resolution #include // optional - needed for MS IP Helper // #define ALL required constants HERE, not inline // #define is a macro, don't terminate with ';' For example... #define RCVBUFSIZ 50 // declare any functions located in other .c files here void DisplayFatalErr(char* errMsg); // writes error message before abnormal termination void main(int argc, char* argv[]) { // Declare ALL variables and structures for main() HERE, NOT INLINE (including the following...) WSADATA wsaData; // contains details about WinSock DLL implementation struct sockaddr_in6 serverInfo; // standard IPv6 structure that holds server socket info char* serverIP; int serverPort; char* message; int messageLen; int remaining; int sock; int bytesSent; int offset; char rcvBuf[RCVBUFSIZ]; int bytesRead; // Verify correct number of command line arguments if (argc != 4) { fprintf(stderr, "Invalid number of arguments! "); exit(1); // ...and terminate with abnormal termination code (1) } serverIP = argv[1]; serverPort = atoi(argv[2]); message = argv[3]; messageLen = 0; while (message[messageLen] != '\0') { messageLen++; } if (WSAStartup(MAKEWORD(2, 0), &wsaData)) { fprintf(stderr, "Unable to initialize Winsock. "); exit(1); } sock = socket(AF_INET6, SOCK_STREAM, IPPROTO_TCP); if (sock == SOCKET_ERROR) { DisplayFatalErr("socket() function failed."); } else { printf("Socket created successfully. "); } int perrno = -1; int v6Only = 0; if ((perrno = setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, (char*)&v6Only, sizeof(v6Only))) != 0) { DisplayFatalErr("setsocket() function failed."); } memset(&serverInfo, 0, sizeof(serverInfo)); serverInfo.sin6_family = AF_INET6; serverInfo.sin6_port = htons(serverPort); if (inet_pton(AF_INET6, serverIP, &serverInfo.sin6_addr) == 0) { char serverMappedIP[32]; char mappedPrefix[] = "::ffff:"; if (inet_pton(AF_INET6, serverMappedIP, &serverInfo.sin6_addr) == 0) { DisplayFatalErr("Unable to parse IP address"); } } if (connect(sock, (struct sockaddr*)&serverInfo, sizeof(serverInfo)) < 0) { DisplayFatalErr("Unable to connect to server"); } else { printf("Connected to server successfully. "); } remaining = messageLen; offset = 0; while (remaining) { bytesSent = send(sock, message + offset, remaining, 0); if (bytesSent == SOCKET_ERROR) { DisplayFatalErr("Unable to send message to server"); } else { offset += bytesSent; remaining -= bytesSent; } } memset(rcvBuf, 0, RCVBUFSIZ); remaining = messageLen; offset = 0; while (remaining) { bytesRead = recv(sock, rcvBuf + offset, RCVBUFSIZ - 1 - offset, 0); if (bytesRead < 0) { DisplayFatalErr("Unable to retrieve response from server"); } else if (bytesRead == 0) { break; } else { offset += bytesRead; remaining -= bytesRead; } } // Close the TCP connection (send a FIN) & print appropriate message. closesocket(sock); printf("Socket closed. "); // Release the Winsock DLL WSACleanup(); exit(0); }

DisplayFatalErr.c

// Minimum required header files for C Winsock program

#include // for print functions

#include // for exit()

#include // for WSAGetLastError()

void DisplayFatalErr(char *errMsg) {

fprintf(stderr, "%s: %d ", errMsg, WSAGetLastError()); // Returns error code from current task or thread

WSACleanup();

exit(1);

}

Step by Step Solution

There are 3 Steps involved in it

Step: 1

blur-text-image

Get Instant Access to Expert-Tailored Solutions

See step-by-step solutions with expert insights and AI powered tools for academic success

Step: 2

blur-text-image

Step: 3

blur-text-image

Ace Your Homework with AI

Get the answers you need in no time with our AI-driven, step-by-step assistance

Get Started

Recommended Textbook for

Automating Access Databases With Macros

Authors: Fish Davis

1st Edition

1797816349, 978-1797816340

More Books

Students also viewed these Databases questions