作业要求:
You need to develop the simplest instant messaging system (chat, messenger)
Server
Must receive messages from clients and send messages to all connected clients. Use threads to work with multiple clients. The name of the binary file being executed must be server. The server must have a console interface in the parameters to which is transferred: port. The server have to support ipv4 and ipv6 protocols
Client
Each client must have own nickname, set by the user. When you receive a message from another client, the screen should display the time of receiving the message, the user-sender's nickname, and the text of the message. An example: {05:20} [John] Hi!
The client must have a console interface. The name of the client for binary file. The client accepts the work options through the command line arguments in the following order: server address, port, nickname. The client have to support ipv4 and ipv6 protocols
To prevent the received (incoming) messages from interfering with the user's typing, it is suggested that a separate mode of sending a message, for example, when the m key is pressed, the user enters his message, new messages from other users are temporarily not displayed, after sending the message (by Enter) the mode is automatically turned off.
Protocol
Client->Server
Nickname size
Nick
Body size
Body
4 bytes
Nickname size bytes
4 bytes
Data size bytes
Network format
-
Network format
-
Server->Client
Nickname size
Nick
Body size
Body
Data size
Date
4 bytes
Nickname size bytes
4 bytes
Data size bytes
4 bytes
Date size bytes
Network format
-
Network format
-
Network format
-
Features that are not required of the server and the client
Client registration, authorization, authentication
More than one channel of communication
Keeping your correspondence history
Processing time zones
Working with languages other than English
Requirements
The server and the client must be written in the language of the C/C++
Make should be used as an build system
The code must be successfully compiled and worked for Linux and MacOS
Valgrind and Google Thread Sanitizer should not find errors in the code
The directory structure of the project looks like this:
├── Dockerfile
├── server.cpp
├── client.cpp
├── Makefile
└── README.md
It is forbidden to modify Makefile/README.md/.clang-format/.gitlab-ci.yml and other hidden files in this directory. The rest of the files can be changed at your discretion. You can also add new cpp/h files if necessary. If you want to use CMake instead of GMake, you can add **CMakeLists.txt , but do not forget that ** Makefile is forbidden to touch.
client.cpp代码如下:
#include <stdio.h>
#include <stdlib.h>
#include <netdb.h>
#include <netinet/in.h>
#include <unistd.h>
#include <string.h>
int main(int argc, char *argv[]) {
(void)argc;
(void)argv;
int sockfd, n;
uint16_t portno;
struct sockaddr_in serv_addr;
struct hostent *server;
char buffer[256];
if (argc < 3) {
fprintf(stderr, "usage %s hostname port\n", argv[0]);
exit(0);
}
portno = (uint16_t)atoi(argv[2]);
/* Create a socket point */
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0) {
perror("ERROR opening socket");
exit(1);
}
server = gethostbyname(argv[1]);
if (server == NULL) {
fprintf(stderr, "ERROR, no such host\n");
exit(0);
}
bzero((char *)&serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
bcopy(server->h_addr, (char *)&serv_addr.sin_addr.s_addr,
(size_t)server->h_length);
serv_addr.sin_port = htons(portno);
/* Now connect to the server */
if (connect(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) {
perror("ERROR connecting");
exit(1);
}
/* Now ask for a message from the user, this message
* will be read by server
*/
printf("Please enter the message: ");
bzero(buffer, 256);
if (fgets(buffer, 255, stdin) == NULL) {
perror("ERROR reading from stdin");
exit(1);
}
/* Send message to the server */
n = write(sockfd, buffer, strlen(buffer));
if (n < 0) {
perror("ERROR writing to socket");
exit(1);
}
/* Now read server response */
bzero(buffer, 256);
n = read(sockfd, buffer, 255);
if (n < 0) {
perror("ERROR reading from socket");
exit(1);
}
printf("%s\n", buffer);
return 0;
}
server.cpp代码如下:
#include <stdio.h>
#include <stdlib.h>
#include <netdb.h>
#include <netinet/in.h>
#include <unistd.h>
#include <string.h>
int main(int argc, char *argv[]) {
(void)argc;
(void)argv;
int sockfd, newsockfd;
uint16_t portno;
unsigned int clilen;
char buffer[256];
struct sockaddr_in serv_addr, cli_addr;
ssize_t n;
/* First call to socket() function */
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0) {
perror("ERROR opening socket");
exit(1);
}
/* Initialize socket structure */
bzero((char *)&serv_addr, sizeof(serv_addr));
portno = 5001;
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = INADDR_ANY;
serv_addr.sin_port = htons(portno);
/* Now bind the host address using bind() call.*/
if (bind(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) {
perror("ERROR on binding");
exit(1);
}
/* Now start listening for the clients, here process will
* go in sleep mode and will wait for the incoming connection
*/
listen(sockfd, 5);
clilen = sizeof(cli_addr);
/* Accept actual connection from the client */
newsockfd = accept(sockfd, (struct sockaddr *)&cli_addr, &clilen);
if (newsockfd < 0) {
perror("ERROR on accept");
exit(1);
}
/* If connection is established then start communicating */
bzero(buffer, 256);
n = read(newsockfd, buffer, 255);
if (n < 0) {
perror("ERROR reading from socket");
exit(1);
}
printf("Here is the message: %s\n", buffer);
/* Write a response to the client */
n = write(newsockfd, "I got your message", 18);
if (n < 0) {
perror("ERROR writing to socket");
exit(1);
}
return 0;
}
在此代码的基础上修改,不要动原有的代码,标出修改的地方