Skip to content

Instantly share code, notes, and snippets.

@yanxurui
Created June 4, 2017 04:53
Show Gist options
  • Save yanxurui/daf62173001c411726bf7591a644b7cf to your computer and use it in GitHub Desktop.
Save yanxurui/daf62173001c411726bf7591a644b7cf to your computer and use it in GitHub Desktop.
chat room example based on multithread
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <netdb.h>
#include <netinet/in.h>
#include <pthread.h>
#define BUFFER_SIZE 1024
int sd;
void* recieve_handler(void *);
int main(int argc, char *argv[])
{
struct sockaddr_in addr;
if (argc < 3) {
fprintf(stderr,"usage %s hostname port\n", argv[0]);
exit(0);
}
if ((sd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
{
perror("socket error");
return -1;
}
bzero(&addr, sizeof(addr));
struct hostent *server = gethostbyname(argv[1]);
if (server == NULL) {
perror("ERROR, no such host\n");
return -1;
}
addr.sin_family = AF_INET;
bcopy((char *)server->h_addr, (char *)&addr.sin_addr.s_addr, server->h_length);
addr.sin_port = htons(atoi(argv[2]));
if(connect(sd, (struct sockaddr *)&addr, sizeof addr) < 0)
{
perror("Connect error");
return -1;
}
printf("connected successfully!\n");
// receive in another thread
pthread_t client_thread;
pthread_create (&client_thread, NULL, &recieve_handler, NULL);
char buffer[BUFFER_SIZE] = "";
ssize_t write;
// read input and send in the main thread
while(1)
{
fgets(buffer, BUFFER_SIZE, stdin);
if(strcmp(buffer, "quit\n") == 0) {
close(sd);
break;
}
else {
write = send(sd, buffer, strlen(buffer), 0);
if (write<0) {
perror("send error");
break;
}
}
}
return 0;
}
void* recieve_handler(void* arg)
{
char buffer[BUFFER_SIZE] = "";
ssize_t read;
while(1)
{
read = recv(sd, buffer, BUFFER_SIZE, 0);
if(read < 0)
{
perror("read error");
break;
}
else if(read == 0)
{
close(sd);
perror("read error, server might close");
}
else {
printf(buffer);
bzero(buffer, BUFFER_SIZE);
}
}
exit(0); // exit the process
return NULL;
}
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <pthread.h>
#define BUFFER_SIZE 1024
#define MAX_CLIENT 1000
int online_clients = 0;
char* clients[MAX_CLIENT] = {NULL};
void* connection_handler(void *);
int main(int argc, char *argv[])
{
int sd;
struct sockaddr_in addr, client_addr;
socklen_t client_len = sizeof(client_addr);
if (argc < 2) {
fprintf(stderr,"usage %s port\n", argv[0]);
exit(0);
}
if( (sd = socket(PF_INET, SOCK_STREAM, 0)) < 0 )
{
perror("socket error");
return -1;
}
bzero(&addr, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_port = htons(atoi(argv[1]));
addr.sin_addr.s_addr = INADDR_ANY;
if (bind(sd, (struct sockaddr*) &addr, sizeof(addr)) != 0)
{
perror("bind error");
return -1;
}
if (listen(sd, 2) < 0)
{
perror("listen error");
return -1;
}
while(1)
{
int client_sd = accept(sd, (struct sockaddr *)&client_addr, &client_len);
if (client_sd < 0)
{
perror("accept error");
return -1;
}
if (client_sd >= MAX_CLIENT)
{
perror("too many clients");
close(client_sd);
return -1;
}
clients[client_sd] = (char *)malloc(sizeof(char)*30);
sprintf(clients[client_sd], "%s:%d", inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port));
printf("Connected with %s\n", clients[client_sd]);
online_clients++;
printf("%d client(s) online.\n", online_clients);
pthread_t client_thread;
pthread_create (&client_thread, NULL, &connection_handler, &client_sd);
}
return 0;
}
void* connection_handler(void* socket)
{
int client_sd = *(int*)socket;
char buffer[BUFFER_SIZE];
ssize_t read;
while(1)
{
read = recv(client_sd, buffer, BUFFER_SIZE, 0);
if(read < 0)
{
perror("read error");
break;
}
if(read == 0)
{
perror("peer might close");
clients[client_sd] = NULL;
online_clients--;
printf("%d client(s) online.\n", online_clients);
break;
}
sprintf(buffer+read-1, "(%s)\n", clients[client_sd]);
for(int i=0,j=0; i<online_clients;i++)
{
while(clients[j] == NULL) j++;
if(j != client_sd) {
send(j, buffer, strlen(buffer), 0);
}
j++;
}
printf("message: %s", buffer);
bzero(buffer, BUFFER_SIZE);
}
free(buffer);
return NULL;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment