This Server handles clients communicating with each other. Because I was not willing to actually give every client a name, they are named by their socket's file descriptor. This is my first application which actually is able to communicate using the INET. It is also my first really multithreaded application.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <pthread.h>
#include <stdbool.h>
#define BUFLEN 255
#define MAX_CONNECTIONS 128
#define MAX_NAME_LENGTH 30
void delete_socket(int socketid);
void* job_read(void*);
void* job_write(void*);
//Global Variables
FILE* plogfile;
int socket_ids[MAX_CONNECTIONS];
bool endprogramm = false;
int open_cnncts = 0;
pthread_mutex_t socketids_changingMutex;
void error(const char* msg){
perror(msg);
exit(1);
}
int main(int argc, char* argv[]) {
printf("Server started...\n");
if(argc < 2){
fprintf(stderr, "You must provide a port number");
exit(EXIT_FAILURE);
}
if(argc == 3){
plogfile = fopen(argv[2], "w");
} else {
plogfile = fopen("logfile.txt", "w");
}
stderr = plogfile;
int sockfd;
uint16_t portnum;
//Create nmutthread
if(pthread_mutex_init(&socketids_changingMutex, NULL) < 0){
error("Could not initialize Mutex");
}
//Initialzing threads and create writethread
pthread_t writethread;
pthread_create(&writethread, NULL, job_write, NULL);
//Setup for connections
struct sockaddr_in serv_add;
struct sockaddr_in cli_adr;
socklen_t clilen;
clilen = sizeof(cli_adr);
bzero((char*)&serv_add, sizeof(struct sockaddr_in));
portnum = (uint16_t)atoi(argv[1]);
serv_add.sin_family = AF_INET;
serv_add.sin_addr.s_addr = INADDR_ANY;
serv_add.sin_port = htons(portnum);
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if(sockfd < 0){
error("Error opening socket.");
}
if(bind(sockfd, (struct sockaddr*) (&serv_add), sizeof(serv_add)) < 0){
error("Binding failed.");
}
fprintf(plogfile,"Listening....");
listen(sockfd, MAX_CONNECTIONS);
for(open_cnncts = 0; (!endprogramm); /*mutex needs to be set*/ ){
socket_ids[open_cnncts] = accept(sockfd, (struct sockaddr*) &cli_adr, &clilen);
pthread_mutex_lock(&socketids_changingMutex);
fprintf(plogfile,"Client connected.\n");
pthread_t thread;
pthread_create(&thread , NULL, job_read, (void*)&socket_ids[open_cnncts]);
open_cnncts++;
pthread_mutex_unlock(&socketids_changingMutex);
}
endprogramm = true;
close(sockfd);
pthread_join(writethread, NULL);
pthread_mutex_destroy(&socketids_changingMutex);
return EXIT_SUCCESS;
}
void* job_read(void * p){
int* socketp = (int*)p;
int newsockfd = (*socketp);
ssize_t n; //Error catching variable
ssize_t m; //Error catching variable
char buffer[BUFLEN];
char name[MAX_NAME_LENGTH];
sprintf(name, "Client %d: ", newsockfd);
while(!endprogramm){
bzero(buffer, BUFLEN);
n = read(newsockfd, buffer, BUFLEN);
if(n<0){
printf("Buffer: %s", buffer);
error("Reading Failed");
}
if(n == 0){
delete_socket(newsockfd);
pthread_exit(NULL);
}
pthread_mutex_lock(&socketids_changingMutex);
for(int i = 0; i < open_cnncts; i++){
if(socket_ids[i] == newsockfd){
continue;
}
m = write(socket_ids[i], name, strlen(name));
n = write(socket_ids[i], buffer, strlen(buffer));
if(n < 0 | m < 0){
error("Writing failed");
}
}
pthread_mutex_unlock(&socketids_changingMutex);
printf("%s%s", name, buffer);
}
delete_socket(newsockfd);
pthread_exit( NULL );
}
void* job_write(void* args){
(void)args;
fprintf(plogfile, "Started writing thread...\n");
ssize_t n; //Error catching variable
ssize_t m; //Error catching variable
char buffer[BUFLEN];
char* name = "Server: \0";
while(!endprogramm) {
fgets(buffer, BUFLEN, stdin);
pthread_mutex_lock(&socketids_changingMutex);
for(int i = 0; i < open_cnncts; i++){
m = write(socket_ids[i], name, strlen(name));
n = write(socket_ids[i], buffer, strlen(buffer));
if(n < 0 | m < 0){
printf("Writing failed");
}
}
pthread_mutex_unlock(&socketids_changingMutex);
if(strcmp("Bye\n", buffer) == 0){
exit(EXIT_SUCCESS);
}
}
endprogramm = true;
pthread_exit( NULL );
}
void delete_socket(int socketid){
bool found = false;
for(int i = 0; i < open_cnncts; i++){
if(found){
socket_ids[i-1] = socket_ids[i];
}
if(socket_ids[i] == socketid){
close(socketid);
found = true;
}
}
if(found){
open_cnncts--;
}
}
Obviously, this code needs improvement, so just feel free to criticize everything criticizable, especially about array-, thread-, and mutex-handling.