HELP!!!
Need help writing a client-server chat room using IRC application in c++.
I'm having issues getting my code to run like the below example:
Client: NICK john
Client: USER john 0 * :Bob John
Server: :babbleServer 001 :Welcome john
Client: NICK
Server: :babbleServer 431 :No nickname given
Client: TIME
Server: :babbleServer 391 babbleServer :Sun Mar 5 22:34:56 UTC 2022
Client: QUIT
//////////////
instead it is doing this:
Client: NICK john
Client: Nickname set to NICK
Client: USER john 0 * :Bob John
Client: User registered
Server: : 001 :Welcome NICK
Client: QUIT
Server: : 431:Unknown command
Server: Client disconnected
////////////////////////////
Below is my code so far
client.cpp
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <netdb.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <iostream>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <cstring>
#include <sstream>
#include <vector>
#include <string>
#include <ctime>
using namespace std;
int main() {
int sock = 0;
struct sockaddr_in serv_addr;
char buffer[1024] = {0};
string nickname;
// Create socket
if((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
cout << "Socket creation error" << endl;
return -1;
}
// Set server address
memset(&serv_addr, '0', sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(555);
if(inet_pton(AF_INET, "192.168.0.10", &serv_addr.sin_addr) <= 0) {
cout << "Invalid address/ Address not supported" << endl;
return -1;
}
// Connect to server
if(connect(sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) {
cout << "Connection failed" << endl;
return -1;
}
// Send NICK and USER commands to register client with server
//cout << "Enter nickname: ";
getline(cin, nickname);
/* if(cin.fail()) {
cerr << "Input error" << endl;
return -1;
} */
string message = "NICK " + nickname + "\n";
send(sock, message.c_str(), message.length(), 0);
/* if(send(sock, message.c_str(), message.length(), 0) != message.length()) {
cerr << "Error sending data" << endl;
return -1;
} */
message = "USER " + nickname + " 0 * :" + nickname + "\n";
send(sock, message.c_str(), message.length(), 0);
// Receive messages from server
while (true) {
memset(buffer, 0, sizeof(buffer));
int valread = read(sock, buffer, 1024);
if (valread < 0) {
cout << "Error reading from socket" << endl;
break;
} else if (valread == 0) {
cout << "Server closed connection" << endl;
break;
}
cout << buffer;
string input;
getline(cin, input);
if(input == "QUIT") {
string message = "QUIT\n";
send(sock, message.c_str(), message.length(), 0);
break;
}
message = input + "\n";
send(sock, message.c_str(), message.length(), 0);
}
close(sock);
return 0;
}
///////////////////////
server.cpp
#include <iostream>
#include <sstream>
#include <vector>
#include <string>
#include <cstring>
#include <ctime>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
using namespace std;
// Helper function to split a string into a vector of strings
vector<string> split(const string &s, char delimiter) {
vector<string> tokens;
stringstream ss(s);
string token;
while(getline(ss, token, delimiter)) {
tokens.push_back(token);
}
return tokens;
}
int main() {
int server_fd, new_socket;
struct sockaddr_in address;
int opt = 1;
int addrlen = sizeof(address);
char buffer[1024] = {0};
vector<string> clients;
// Create server socket
if((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0) {
perror("socket failed");
exit(EXIT_FAILURE);
}
// Set socket options
if(setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, &opt, sizeof(opt))) {
perror("setsockopt");
exit(EXIT_FAILURE);
}
// Set server address
address.sin_family = AF_INET;
address.sin_addr.s_addr = INADDR_ANY;
address.sin_port = htons(555);
// Bind socket to address
if(bind(server_fd, (struct sockaddr *)&address, sizeof(address))<0) {
perror("bind failed");
exit(EXIT_FAILURE);
}
// Start listening for incoming connections
if(listen(server_fd, 3) < 0) {
perror("listen");
exit(EXIT_FAILURE);
}
while ((new_socket = accept(server_fd, (struct sockaddr *)&address, (socklen_t*)&addrlen))) {
// Receive messages from client
while (true) {
memset(buffer, 0, sizeof(buffer));
int valread = read(new_socket, buffer, 1024);
if(valread < 0) {
cout << "Error reading from socket" << endl;
break;
}
else if(valread == 0) {
cout << "Client disconnected" << endl;
break;
}
// Parse message from client
vector<string> tokens = split(buffer, ' ');
string command = tokens[0];
if (command == "NICK") {
if(tokens.size() < 2) {
cout << ":server 431 :No nickname given" << endl;
string response = "No nickname given\n";
send(new_socket, response.c_str(), response.length(), 0);
continue;
}
// Set client nickname
clients.push_back(tokens[1]);
string response = "Nickname set to " + tokens[1] + "\n";
send(new_socket, response.c_str(), response.length(), 0);
} else if (command == "USER") {
// Register user
for(auto it = clients.begin(); it != clients.end(); ++it)
cout << ":" << " 001" << " :Welcome to Calculus IRC " << *it << endl;
string response = "User registered\n";
send(new_socket, response.c_str(), response.length(), 0);
} else if (command == "JOIN") {
// Join channel
string response = "Joined channel " + tokens[1] + "\n";
send(new_socket, response.c_str(), response.length(), 0);
} else if (command == "PART") {
// Leave channel
string response = "Left channel " + tokens[1] + "\n";
send(new_socket, response.c_str(), response.length(), 0);
} else if (command == "TOPIC") {
if (tokens.size() == 2) {
// View channel topic
string response = "Channel topic: " + tokens[1] + "\n";
send(new_socket, response.c_str(), response.length(), 0);
} else if (tokens.size() == 3 && tokens[2] == "") {
// Clear channel topic
string response = "Channel topic cleared\n";
send(new_socket, response.c_str(), response.length(), 0);
} else {
// Set channel topic
string response = "Set channel topic to " + tokens[2] + "\n";
send(new_socket, response.c_str(), response.length(), 0);
}
} else if (command == "NAMES") {
// List all clients connected to the server
string response = "Connected clients:\n";
for (string client : clients) {
response += client + "\n";
}
send(new_socket, response.c_str(), response.length(), 0);
} else if (command == "PRIVMSG") {
// Send message to other client(s)
string recipient = tokens[1];
string message = tokens[2];
string sender = "";
for (string client : clients) {
if (client == recipient) {
sender = "Server";
break;
}
}
if (sender == "") {
sender = tokens[0].substr(1);
}
string response = "<" + sender + "> " + message + "\n";
send(new_socket, response.c_str(), response.length(), 0);
} else if (command == "TIME") {
// Send server time
time_t now = time(0);
char* dt = ctime(&now);
string response = "Server time: " + string(dt);
send(new_socket, response.c_str(), response.length(), 0);
} else if (command == "QUIT") {
close(new_socket);
cout << "Client disconnected" << endl;
break;
}
// Unknown list of commands
else {
cout << ":" << " 431" << ":Unknown command" << endl;
string response = "Unknown command\n";
send(new_socket, response.c_str(), response.length(), 0);
}
}
}
return 0;
}