├── .gitignore ├── README.md ├── client.cpp ├── screenshot.png └── server.cpp /.gitignore: -------------------------------------------------------------------------------- 1 | client 2 | server -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Chatroom Application 2 | 3 | A chatroom built in C++ using the concepts of socket programming and multi-threading. It supports chatting among multiple clients. 4 | 5 | ![](/screenshot.png) 6 | ## How to run 7 | 8 | 1. Clone this repository 9 | 2. Run the following commands in your terminal : 10 | ``` 11 | g++ server.cpp -lpthread -o server 12 | g++ client.cpp -lpthread -o client 13 | ``` 14 | 3. To run the server application, use this command in the terminal : 15 | ``` 16 | ./server 17 | ``` 18 | 19 | 4. Now, open another terminal and use this command to run the client application : 20 | ``` 21 | ./client 22 | ``` 23 | 24 | 5. For opening multiple client applications, repeat step 4. -------------------------------------------------------------------------------- /client.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #define MAX_LEN 200 13 | #define NUM_COLORS 6 14 | 15 | using namespace std; 16 | 17 | bool exit_flag=false; 18 | thread t_send, t_recv; 19 | int client_socket; 20 | string def_col="\033[0m"; 21 | string colors[]={"\033[31m", "\033[32m", "\033[33m", "\033[34m", "\033[35m", "\033[36m"}; 22 | 23 | void catch_ctrl_c(int signal); 24 | string color(int code); 25 | int eraseText(int cnt); 26 | void send_message(int client_socket); 27 | void recv_message(int client_socket); 28 | 29 | int main() 30 | { 31 | if((client_socket=socket(AF_INET,SOCK_STREAM,0))==-1) 32 | { 33 | perror("socket: "); 34 | exit(-1); 35 | } 36 | 37 | struct sockaddr_in client; 38 | client.sin_family=AF_INET; 39 | client.sin_port=htons(10000); // Port no. of server 40 | client.sin_addr.s_addr=INADDR_ANY; 41 | //client.sin_addr.s_addr=inet_addr("127.0.0.1"); // Provide IP address of server 42 | bzero(&client.sin_zero,0); 43 | 44 | if((connect(client_socket,(struct sockaddr *)&client,sizeof(struct sockaddr_in)))==-1) 45 | { 46 | perror("connect: "); 47 | exit(-1); 48 | } 49 | signal(SIGINT, catch_ctrl_c); 50 | char name[MAX_LEN]; 51 | cout<<"Enter your name : "; 52 | cin.getline(name,MAX_LEN); 53 | send(client_socket,name,sizeof(name),0); 54 | 55 | cout< 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #define MAX_LEN 200 12 | #define NUM_COLORS 6 13 | 14 | using namespace std; 15 | 16 | struct terminal 17 | { 18 | int id; 19 | string name; 20 | int socket; 21 | thread th; 22 | }; 23 | 24 | vector clients; 25 | string def_col="\033[0m"; 26 | string colors[]={"\033[31m", "\033[32m", "\033[33m", "\033[34m", "\033[35m","\033[36m"}; 27 | int seed=0; 28 | mutex cout_mtx,clients_mtx; 29 | 30 | string color(int code); 31 | void set_name(int id, char name[]); 32 | void shared_print(string str, bool endLine); 33 | int broadcast_message(string message, int sender_id); 34 | int broadcast_message(int num, int sender_id); 35 | void end_connection(int id); 36 | void handle_client(int client_socket, int id); 37 | 38 | int main() 39 | { 40 | int server_socket; 41 | if((server_socket=socket(AF_INET,SOCK_STREAM,0))==-1) 42 | { 43 | perror("socket: "); 44 | exit(-1); 45 | } 46 | 47 | struct sockaddr_in server; 48 | server.sin_family=AF_INET; 49 | server.sin_port=htons(10000); 50 | server.sin_addr.s_addr=INADDR_ANY; 51 | bzero(&server.sin_zero,0); 52 | 53 | if((bind(server_socket,(struct sockaddr *)&server,sizeof(struct sockaddr_in)))==-1) 54 | { 55 | perror("bind error: "); 56 | exit(-1); 57 | } 58 | 59 | if((listen(server_socket,8))==-1) 60 | { 61 | perror("listen error: "); 62 | exit(-1); 63 | } 64 | 65 | struct sockaddr_in client; 66 | int client_socket; 67 | unsigned int len=sizeof(sockaddr_in); 68 | 69 | cout< guard(clients_mtx); 81 | clients.push_back({seed, string("Anonymous"),client_socket,(move(t))}); 82 | } 83 | 84 | for(int i=0; i guard(cout_mtx); 115 | cout< guard(clients_mtx); 153 | clients[i].th.detach(); 154 | clients.erase(clients.begin()+i); 155 | close(clients[i].socket); 156 | break; 157 | } 158 | } 159 | } 160 | 161 | void handle_client(int client_socket, int id) 162 | { 163 | char name[MAX_LEN],str[MAX_LEN]; 164 | recv(client_socket,name,sizeof(name),0); 165 | set_name(id,name); 166 | 167 | // Display welcome message 168 | string welcome_message=string(name)+string(" has joined"); 169 | broadcast_message("#NULL",id); 170 | broadcast_message(id,id); 171 | broadcast_message(welcome_message,id); 172 | shared_print(color(id)+welcome_message+def_col); 173 | 174 | while(1) 175 | { 176 | int bytes_received=recv(client_socket,str,sizeof(str),0); 177 | if(bytes_received<=0) 178 | return; 179 | if(strcmp(str,"#exit")==0) 180 | { 181 | // Display leaving message 182 | string message=string(name)+string(" has left"); 183 | broadcast_message("#NULL",id); 184 | broadcast_message(id,id); 185 | broadcast_message(message,id); 186 | shared_print(color(id)+message+def_col); 187 | end_connection(id); 188 | return; 189 | } 190 | broadcast_message(string(name),id); 191 | broadcast_message(id,id); 192 | broadcast_message(string(str),id); 193 | shared_print(color(id)+name+" : "+def_col+str); 194 | } 195 | } 196 | --------------------------------------------------------------------------------