asynchronous socket server, killing thread c - c

Im having some kind of trouble on my asynchronous socket server in c, i though in moving it to java, but first i want to solve this problem.
i have a detached thread for each connection (not client), when its done it closes it, im having a problem when the server gets 2 connections at the same time, it kind of leave the old behind and starts with the new...
this is the code:
int main( int argc, char *argv[] )
{
int server_portno=1111;
int sockfd, newsockfd,option=1;
int *new_sock;
socklen_t clilen;
struct sockaddr_in serv_addr, cli_addr;
/* First call to socket() function */
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0)
{
addLog("ERROR opening socket\n");
exit(1);
}
/* Initialize socket structure */
bzero((char *) &serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = INADDR_ANY;
serv_addr.sin_port = htons(server_portno);
/* Now bind the host address using bind() call.*/
if (bind(sockfd, (struct sockaddr *) &serv_addr,
sizeof(serv_addr)) < 0)
{
addLog("ERROR on binding\n");
exit(1);
}
if(setsockopt(sockfd,SOL_SOCKET,SO_REUSEADDR,&option,sizeof(option)) < 0)
{
addLog("setsockopt failed\n");
close(sockfd);
exit(2);
}
/* 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);
while((newsockfd = accept(sockfd,
(struct sockaddr *) &cli_addr, &clilen)))
{
addLog("connection accepted\n");
pthread_t thread;
pthread_attr_t tattr;
new_sock =malloc(sizeof(int));
*new_sock = newsockfd;
pthread_attr_init(&tattr);
pthread_attr_setdetachstate(&tattr,PTHREAD_CREATE_DETACHED);
if(pthread_create(&thread,&tattr,doprocessing,new_sock)<0)
{
addLog("could not create thread\n");
return 1;
}
addLog("Handler assigned\n");
}
return 0;
}
void addLog(char info[300])
{
printf("%s",info);
return;
}
void *doprocessing (void* sock_info)
{
int *sock=(int*)sock_info;
int n;
char buffer[10000],logInfo[200];
bzero(buffer,10000);
n = read(*sock,buffer,10000);
if (n < 0)
{
addLog("ERROR reading from socket\n");
exit(1);
}
sprintf(logInfo,"Here is the message: %s\n",buffer);
addLog(logInfo);
/*
* do something
*/
addLog("Closing port\n");
close(*sock);
addLog("freeing port\n");
free(sock_info);
addLog("exiting thread\n");
pthread_exit(NULL);
}
this is my client code, i divide it by 4 functions, starts, stop, send and receive:
#define CONNECTION_STARTED 1
#define CONNECTION_NOT_STARTED 0
#..all return macros here too..
int sockfd;
int status=CONNECTION_NOT_STARTED;
struct sockaddr_in serv_addr;
int socket_start_connection()
{
addLog("starting connection\n");
if(status==CONNECTION_STARTED)
return SOCKET_SUCCESS_CONNECTION_OPEN;
char *serverAddr=SERVER_HOSTNAME;//example.ex
int portno,valopt,res;
struct hostent *server;
struct timeval tv;
socklen_t lon;
fd_set myset;
long arg;
sockfd=-1;
portno =SERVER_PORT;//1111
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0)
{
addLog("ERROR opening socket");
return SOCKET_ERROR_OPENING_PORT;
}
server=gethostbyname(serverAddr);
if (server == NULL)
{
addLog("ERROR no such host");
return SOCKET_ERROR_HOST_NOT_FOUND;
}
bzero((char *) &serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
bcopy((char *)server->h_addr,
(char *)&serv_addr.sin_addr.s_addr,
server->h_length);
serv_addr.sin_port = htons(portno);
if( (arg = fcntl(sockfd, F_GETFL, NULL)) < 0)
{
addLog("Error fcntl , F_GETFL");
return SOCKET_ERROR_TIMEOUT_F_GETFL;
}
arg |= O_NONBLOCK;
if( fcntl(sockfd, F_SETFL, arg) < 0)
{
addLog("Error fcntl, F_SETFL");
return SOCKET_ERROR_TIMEOUT_F_SETFL;
}
res=connect(sockfd,(struct sockaddr *) &serv_addr,sizeof(serv_addr));
if(res<0)
{
if(errno==EINPROGRESS)
{
do
{
tv.tv_sec = SOCKET_CONNECTION_TIME_LIMIT;//something like 60 seconds
tv.tv_usec = 0;
FD_ZERO(&myset);
FD_SET(sockfd, &myset);
res = select(sockfd+1, NULL, &myset, NULL, &tv);
if (res < 0 && errno != EINTR)
{
addLog("Error Connecting to server");
exit(SOCKET_ERROR_CONNECTING_TO_HOST);
}
else if (res > 0)
{
lon = sizeof(int);
if (getsockopt(sockfd, SOL_SOCKET, SO_ERROR, (void*)(&valopt), &lon) < 0)
{
addLog("Error getsockopt");
return SOCKET_ERROR_GETSOCKOPT;
}
// Check the value returned...
if (valopt)
{
addLog("Error in connection to server");
socket_stop_connection();
return SOCKET_ERROR_DELAYED_CONNECTION;
}
break;
}
else
{
addLog("Error, time limited exceed");
socket_stop_connection();
return SOCKET_ERROR_CONNECTION_TIMEOUT;
}
}while(1);
}
}
// Set to blocking mode again...
if( (arg = fcntl(sockfd, F_GETFL, NULL)) < 0)
{
addLog("Error fcntl , F_GETFL");
return SOCKET_ERROR_TIMEOUT_F_GETFL;
}
arg &= (~O_NONBLOCK);
if( fcntl(sockfd, F_SETFL, arg) < 0)
{
addLog("Error fcntl , F_SETFL");
return SOCKET_ERROR_TIMEOUT_F_SETFL;
}
status=CONNECTION_STARTED;
return SOCKET_SUCCESS_CONNECTION_OPEN;
}
int socket_stop_connection()
{
addLog("stopping connection\n");
if(status==CONNECTION_NOT_STARTED)
return SOCKET_ERROR_CLOSING_CONNECTION;
close(sockfd);
status=CONNECTION_NOT_STARTED;
return SOCKET_SUCCESS_CONNECTION_CLOSED;
}
int socket_send_message(char* message)
{
addLog("sending message\n");
if(!status==CONNECTION_STARTED)
{
socket_start_connection();
if(!status==CONNECTION_STARTED)
{
addLog("ERROR NOT CONNECTED");
return SOCKET_ERROR_NOT_CONNECTED;
}
}
int n;
n = write(sockfd,message,strlen(message));
if (n < 0)
{
addLog("ERROR writing to socket");
return SOCKET_ERROR_WRITING_TO_SOCKET;
}
return SOCKET_SUCCESS_MESSAGE_SENT;
}
int socket_receive_message(char* buffer)
{
addLog("receiving message\n");
if(!status==CONNECTION_STARTED)
{
addLog("ERROR NOT CONNECTED");
return SOCKET_ERROR_NOT_CONNECTED;
}
int n;
bzero(buffer,256);
n = read(sockfd,buffer,255);
if (n < 0)
addLog("ERROR reading from socket");
close(sockfd);
sockfd = socket(AF_INET, SOCK_STREAM, 0);
return SOCKET_SUCCESS_MESSAGE_RECEIVED;
}

Related

Segfault in client disconnection

I have a simple client-server program implemented in C where a client can send integers to a server and the server replies with their sums. However, there is a troubling Segmentation fault (core dumped) shown on the server side whenever the client disconnects suddenly. The Client:
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#define PORT 5010
int main(int argc, char **argv) {
char buf[BUFSIZ], buf2[BUFSIZ], message[BUFSIZ], serverReply[BUFSIZ];
int SOCKET;
struct sockaddr_in server;
SOCKET = socket(AF_INET, SOCK_STREAM, 0);
if (SOCKET < 0) {
perror("Could not create socket");
return -1;
}
printf("Socket created\n");
server.sin_addr.s_addr = inet_addr("127.0.0.1");
server.sin_family = AF_INET;
server.sin_port = htons(PORT);
if (connect(SOCKET, (struct sockaddr *) &server, sizeof(struct sockaddr_in)) < 0) {
perror("Could not connect");
return -1;
}
memset(&serverReply, 0, sizeof(serverReply));
printf("Connected to server.\nEnter first number: ");
scanf("%s", buf);
fflush(stdin);
printf("Enter second number: ");
scanf("%s", buf2);
strcat(buf, " ");
strcat(buf, buf2);
strcpy(message, buf);
if (send(SOCKET, message, strlen(message), 0) < 0) {
perror("Failed to send message");
return -1;
}
if (recv(SOCKET, serverReply, sizeof(serverReply), 0) < 0) {
perror("Could not receive message");
return -1;
}
printf("Server: %s", serverReply);
close(SOCKET);
}
The Server:
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <errno.h>
#define PORT 5010
int main(int argc, char *argv[]) {
char msg[BUFSIZ], reply[BUFSIZ];
struct sockaddr_in server, client;
int SOCKET, ACCEPT, READ, sockSize, num1, num2, option = 1, maxClients = 30,
h, clientSocket[maxClients], maxsd, sd, SELECT;
fd_set readfds;
for (h = 0; h < maxClients; h++) {
clientSocket[h] = 0;
}
SOCKET = socket(AF_INET, SOCK_STREAM, 0);
if (SOCKET == -1) {
perror("Could not create socket");
return -1;
}
if (setsockopt(SOCKET, SOL_SOCKET, SO_REUSEADDR, &option, sizeof(option)) == -1) {
perror("Could not set OPTNAME");
return -1;
}
server.sin_family = AF_INET;
server.sin_addr.s_addr = INADDR_ANY;
server.sin_port = htons(PORT);
printf("Created socket.\n");
if (bind(SOCKET, (struct sockaddr *) &server, sizeof(server)) < 0) {
perror("Could not bind");
return -1;
}
if (listen(SOCKET, 1) < 0) {
perror("Listen failed");
return -1;
}
printf("Server is listening.\n");
sockSize = sizeof(struct sockaddr_in);
while (1) {
FD_ZERO(&readfds);
FD_SET(SOCKET, &readfds);
maxsd = SOCKET;
for (h = 0; h < maxClients; h++) {
sd = clientSocket[h];
if (sd > 0) { FD_SET(sd, &readfds); }
if (sd > maxsd) { maxsd = sd; }
}
SELECT = select(maxsd + 1, &readfds, NULL, NULL, NULL);
if ((SELECT < 0) && (errno != EINTR)) {
perror("select error");
}
if (FD_ISSET(SOCKET, &readfds)) {
ACCEPT = accept(SOCKET, (struct sockaddr *) &server, (socklen_t *) &sockSize);
if (ACCEPT < 0) {
perror("Could not accept client");
return -1;
}
for (h = 0; h < maxClients; h++) {
if (clientSocket[h] == 0) {
clientSocket[h] = ACCEPT;
break;
}
}
printf("Client has joined the server.\n");
}
for (h = 0; h < maxClients; h++) {
sd = clientSocket[h];
if (FD_ISSET(sd, &readfds)) {
READ = read(sd, msg, sizeof(msg));
if (READ == -1) {
perror("Could not receive message");
return -1;
}
if (READ == 0) {
printf("Client disconnected\n");
fflush(stdout);
clientSocket[h]=0;
}
int e = 0;
char *p = strtok(msg, " ");
char *arr[2];
while (p != NULL) {
arr[e++] = p;
p = strtok(NULL, " ");
}
num1 = atoi(arr[0]);
num2 = atoi(arr[1]);
if ((strcmp(arr[0], "0") != 0 && num1 != 0) && (strcmp(arr[1], "0") != 0 && num2 != 0)) {
printf("Client: %d, %d\n", num1, num2);
sprintf(reply, "%d\n", num1 + num2);
if (write(sd, reply, strlen(reply)) < 0) {
perror("Could not send message");
return -1;
}
memset(&reply, 0, sizeof(reply));
} else {
printf("Conversion error");
strcpy(reply, "Conversion error.");
if (write(sd, reply, strlen(reply)) < 0) {
perror("Could not send message");
return -1;
}
}
}
}
}
}
How can the segfault be solved? How else can the codes be improved?
The segfault comes from the atoi function since NULL is received. Checking for NULL seems to do the trick...

multiple clients stop and wait with C & UDP

I am implementing stop&wait with c and udp socket programming. with one client it works but with more than one client it dosen't work.
server.c
struct sockaddr_in newAddr;
socklen_t addr_size = sizeof(newAddr);
fd_set rset;
int frame_id = 0;
Frame frame_recv;
Frame frame_send;
int socket_desc = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (socket_desc < 0) {
perror("Socket Creation Failed ");
exit(EXIT_FAILURE);
}
else {
perror("Socket Created ");
}
if (bind(socket_desc, (struct sockaddr *) &server_addr,
sizeof(server_addr)) < 0 ) {
perror("Bind Failed ");
exit(EXIT_FAILURE);
}
else {
perror("Bind Done ");
}
printf("Listening for Messages...\n");
FD_ZERO(&rset);
while (1) {
FD_SET(socket_desc, &rset);
select(socket_desc + 1, &rset, NULL, NULL, NULL);
if (FD_ISSET(socket_desc, &rset)) {
int recv_size = recvfrom(socket_desc, &frame_recv, sizeof(Frame), 0,
(struct sockaddr *) &newAddr, &addr_size);
if (recv_size > 0 && frame_recv.frame_kind == 1 &&
frame_recv.sq_no == frame_id) {
printf("[+]Frame Received: %s\n", frame_recv.packet.data);
frame_send.sq_no = 0;
frame_send.frame_kind = 0;
frame_send.ack = frame_recv.sq_no + 1;
sendto(socket_desc, &frame_send, sizeof(frame_send), 0,
(struct sockaddr*)&newAddr, addr_size);
printf("[+]Ack Send\n");
}
else {
printf("[+]Frame Not Received\n");
break;
}
frame_id ++;
}
}
close(socket_desc);
client.c
char buffer[1024];
socklen_t addr_size;
int frame_id = 0;
Frame frame_send;
Frame frame_recv;
int ack_recv = 1;
int socket_desc = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (socket_desc < 0) {
perror("Socket Creation Failed ");
exit(EXIT_FAILURE);
}
else {
perror("Socket Created ");
}
while (1) {
if (ack_recv == 1) {
frame_send.sq_no = frame_id;
frame_send.frame_kind = 1;
frame_send.ack = 0;
printf("Enter Data: ");
scanf("%s", buffer);
strcpy(frame_send.packet.data, buffer);
sendto(socket_desc, &frame_send, sizeof(Frame), 0,
(struct sockaddr*)&server_addr, sizeof(server_addr));
printf("[+]Frame Send\n");
}
int addr_size = sizeof(server_addr);
int recv_size = recvfrom(socket_desc, &frame_recv, sizeof(frame_recv), 0 ,(struct sockaddr*)&server_addr, &addr_size);
if (recv_size > 0 && frame_recv.sq_no == 0 && frame_recv.ack == frame_id + 1) {
printf("[+]Ack Received\n");
ack_recv = 1;
}
else {
printf("[-]Ack Not Received\n");
ack_recv = 0;
break;
}
frame_id++;
}
close(socket_desc);
header.h
typedef struct packet {
char data[1024];
} Packet;
typedef struct frame {
int frame_kind; //ACK:0, SEQ:1 FIN:2
int sq_no;
int ack;
Packet packet;
} Frame;
I found that frame_recv.sq_no and frame_id have different value when the second client run.
I read questions with same topic, but could not find out the error from my code.

send information to forked process with threads

I have 2 programs, a client and a server, the client can send data to the server, and I want to send all the new data received on the server from one client to the other connected clients with a thread, each connected client has a child process in the server that receives the data, here is an illustration of what I want to do.
server.c :
int main(int argc, char const *argv[]) {
Liste *ListeTache;
int sh_id;
int i,j;
size_t sizeMatrix = sizeof_dm(30,100,sizeof(char));
ListeTache=malloc(sizeof(Liste));
init_Liste(ListeTache);
key_t keyfile = ftok("keyFileIpc.txt",10);
if((sh_id = shmget(keyfile,sizeof(Liste),IPC_CREAT|0666)) == -1) {
perror("shmget");
exit(1);
}
if ((ListeTache = shmat(sh_id, NULL, 0)) == (void *) -1) {
perror("shmat");
exit(1);
}
init_Liste(ListeTache);
printSharedMem(ListeTache->s);
//creation de la socket pour le TCP
int sock = socket(AF_INET, SOCK_STREAM, 0);
if(sock == -1) {
perror("socket error\n");
exit(errno);
}
struct sockaddr_in sin = { 0 };
sin.sin_addr.s_addr = htonl(INADDR_ANY);
sin.sin_family = PF_INET;
sin.sin_port = htons(31470);
if(bind (sock, (struct sockaddr *) &sin, sizeof sin) == -1) {
perror("bind()");
exit(errno);
}
if(listen(sock, 3) == -1) {
perror("listen error\n");
exit(errno);
}
struct sockaddr_in csin = { 0 };
int idSock;
socklen_t lg = sizeof(struct sockaddr_in);
char msg[100];
do {
if ((idSock = accept(sock, (struct sockaddr *) &csin, &lg)) == -1) {
perror("accept error\n");
exit(errno);
}
if (!fork()) {
close(sock);
printSharedMem(ListeTache->s);
printf("i'm here\n");
// we send here the initial data
if(send(idSock, ListeTache, sizeof(Liste), 0) < 0) {
perror("send()");
exit(errno);
}
pthread_t idThread;
do {
if(recv(idSock, &paramsReq, sizeof(paramsReq), 0) < 0) {
perror("paramsReq :recv error\n");
exit(errno);
}
//if recv something from a client then i want to send the change to all the others here
}
else
{
close(idSock);
}
} while (1);
free(ListeTache);
ListeTache=NULL;
shmctl(sh_id, IPC_RMID, NULL);
return 0;
}
client.c
void *listenServ (void *arg) {
paramsListenServ params = *((paramsListenServ *) arg);
paramsRequest paramsReq;
do {
if(recv(params.sockId, &paramsReq, sizeof(paramsReq), 0) < 0) {
perror("recv error\n");
exit(errno);
}
printf("%s \n", paramsReq.requestType);
if (!strcmp(paramsReq.requestType, "addRequest")) {
strcpy(&params.s[paramsReq.taskToModify*100], paramsReq.taskText);
printSharedMemo(params.s);
}
else if (!strcmp(paramsReq.requestType, "swapRequest")) {
char firstTask[100];
strcpy(firstTask, &params.s[paramsReq.tasksToSwap.firstTask*100]);
strcpy(&params.s[paramsReq.tasksToSwap.firstTask*100], &params.s[paramsReq.tasksToSwap.secondTask*100]);
strcpy(&params.s[paramsReq.tasksToSwap.secondTask*100], firstTask);
printSharedMemo(params.s);
}
else if (!strcmp(paramsReq.requestType, "modifyRequest")) {
strcpy(&params.s[paramsReq.taskToModify*100], paramsReq.taskText);
printSharedMemo(params.s);
}
else if (!strcmp(paramsReq.requestType, "deleteRequest")) {
int i = paramsReq.taskToModify;
while (i < 29 && strlen(&params.s[i * 100]) != 0) {
strcpy(&params.s[i*100], &params.s[(i + 1)*100]);
i++;
}
strcpy(&params.s[(paramsReq.head - 1)*100], "");
printSharedMemo(params.s);
}
/*printf("Message reçu du serveur : %s\n", msg);
memset(msg,0, sizeof msg);*/
} while (1);
pthread_exit(NULL);
}
int main(int argc, char const *argv[]) {
//creation d'un socket ppour le TCP
int sock = socket(AF_INET, SOCK_STREAM, 0);
Liste *ListeTache;
ListeTache=malloc(sizeof(Liste));
init_Liste(ListeTache);
int j;
if(sock == -1) {
perror("socket()");
exit(errno);
}
//initialisation de la structure de donné
struct sockaddr_in sin = { 0 };
sin.sin_family = PF_INET;
sin.sin_addr.s_addr = inet_addr("127.0.0.1");
sin.sin_port = htons((short)31470);
//connect to the server
if(connect(sock,(struct sockaddr *) & sin, sizeof(struct sockaddr_in)) == -1) {
perror("connect()");
exit(errno);
}
// we receive the initial data
if(recv(sock,ListeTache,sizeof(Liste), 0) < 0) {
perror("main :recv error\n");
exit(errno);
}
printSharedMemo(ListeTache->s);
pthread_t idThread;
paramsListenServ params;
params.s=ListeTache->s;
params.sockId = sock;
// this thread listen to the send that is in the server
if(pthread_create(&idThread, NULL, listenServ, &params) != 0)
perror("pthread_create");
do {
//do changes
//we send the new data to the server
if(send(sock, &paramsReq, sizeof(paramsReq), 0) < 0) {
perror("send()");
exit(errno);
}
}
}
} while(1<=choice && choice<=4);
close(sock);
printf("La connexion avec le serveur a bien été fermée ! \n");
return 0;
}
My question is, if I use a thread and put it in a fork, how can the thread get the data sent from one client because the socket change from one client to another?

when i run my client program it doesn't connect with my server

this client and server program compiles successfully. run the server it waits for client connection.
but when i run this client program it always shows "connection failed..."
i don't understand why...
server.c
int main()
{
struct sockaddr_in main_server, cli_1_server, cli_2_server;
int main_sock, cli_1_sock, cli_2_sock;
int Len;
char arv_msg[MAXSZ];
//char client_name[20];
// FILE *fp;
//short int RcvByte_1 = 0, RcvByte_2 = 0;
if( ( main_sock = socket(AF_INET, SOCK_STREAM, 0) ) < 0 )
{
printf("socket creation failed...\n");
exit(-1);
}
main_server.sin_family = AF_INET;
main_server.sin_addr.s_addr = inet_addr("127.0.0.1");
main_server.sin_port = htons(10000);
if( ( bind( main_sock, (SA *)&main_server, sizeof(main_server) ) ) < 0)
{
printf("binding failed...\n");
exit(-1);
}
printf("Listining...\n");
listen(main_sock, WAITING);
Len = sizeof(cli_1_server);
if( ( cli_1_sock = accept( main_sock, (SA *)&cli_1_server, &Len ) ) <0)
{
printf("Client 1 request failed...\n");
exit(-1);
}
printf("client 1 connected...\n");
}
client.c
int main()
{
struct sockaddr_in main_server;
int cli_1_sock;
char snd_msg[MAXSZ], rcv_msg[MAXSZ];
int n = 0;
if( ( cli_1_sock = (AF_INET, SOCK_STREAM, 0) ) == -1 )
{
printf("socket creation failed...\n");
exit(-1);
}
main_server.sin_family = AF_INET;
main_server.sin_addr.s_addr = inet_addr("127.0.0.1");
main_server.sin_port = htons(10000);
if( ( connect(cli_1_sock, (SA *)&main_server,sizeof(main_server)))==-1)
{
printf("connection failed...\n");
exit(-1);
}
printf("connected\n");
}
this is my server and client..program
change
cli_1_sock = (AF_INET, SOCK_STREAM, 0)
to
cli_1_sock = socket(AF_INET, SOCK_STREAM, 0)

Socket Programming Send / Recv Before Scanf

Im trying to create connection between 2 clients via a server. In this program, client sends a message to the server and server post it to the target client. But there is a little problem between this operation. Transmitter one cannot send another message before it receive some message or receiver one cannot see the received message before send a message. Video should explain better.
You can find scanf function in below of client.c codes
CLIENT
//
// Created by berkin on 18.12.2016.
//
#include<stdio.h>
#include<sys/socket.h>
#include<arpa/inet.h> // for inet_addr
#include <string.h>
#include <zconf.h>
int main(int argc, char *argv[]) {
int sock;
struct sockaddr_in server;
char message[2000], server_reply[2000];
//Create socket
sock = socket(AF_INET, SOCK_STREAM, 0);
if (sock == -1) {
printf("Could not create socket");
}
server.sin_addr.s_addr = inet_addr("127.0.0.1");
server.sin_family = AF_INET;
server.sin_port = htons(8888);
//Connect to remote server
if (connect(sock, (struct sockaddr *) &server, sizeof(server)) < 0) {
perror("Connect failed. Error");
return 1;
}
puts("Connected to server\n");
//keep communicating with server
while (1) {
printf("> ");
scanf("%[^\n]%*c", message);
fflush(stdin);
//Send some data
if (send(sock, message, strlen(message)+1, 0) < 0) {
puts("Send failed");
return 1;
}
if (recv(sock, server_reply, 2000, 0) < 0) {
puts("recv failed");
break;
}
//Receive a reply from the server
printf ("\033[32;1m %s \033[0m\n",server_reply);
}
close(sock);
return 0;
}
SERVER
#include<stdio.h>
#include<string.h> // for strlen
#include<stdlib.h>
#include<sys/socket.h>
#include<arpa/inet.h> // for inet_addr
#include<unistd.h> // for write
#include<pthread.h> // for threading, link with lpthread
#include "split.h"
#define MAX_CLIENT_NUMBER 100
void *connection_handler(void *);
struct User {
char userName[10];
int clientSocketNo;
};
unsigned int clientNumber = 0;
unsigned int userArrayIndex = 0;
struct User users[MAX_CLIENT_NUMBER];
//FOR GETUSERS COMMAND
void getUsers(int socketNumber) {
char *userString = malloc(100);
if (users[0].userName != NULL) {
strcpy(userString, users[0].userName);
strcat(userString, ",");
} else {
return;
}
for (int i = 1; i < userArrayIndex; ++i) {
strcat(userString, users[i].userName);
strcat(userString, ",");
}
write(socketNumber, userString, strlen(userString) + 1);
}
//AFTER LOGIN COMMAND, ADD TO THE ARRAY
void addUserToArray(char userName[10], int socketNumber) {
printf("Client logged in as %s\n", userName);
strcpy(users[userArrayIndex].userName, userName);
users[userArrayIndex].clientSocketNo = socketNumber;
userArrayIndex++;
}
//LOGIN COMMAND
void loginUser(char userName[10], int socketNumber) {
char *message = "login successful";
write(socketNumber, message, strlen(message) + 1);
addUserToArray(userName, socketNumber);
}
//SEND MESSAGE IF USER FOUND
void sendMessage(struct User user, char *message){
write(user.clientSocketNo,message,strlen(message) + 1);
}
//SEARCH USER FROM ARRAY
struct User searchUser(char searchName[10]){
for (int i = 0; i < userArrayIndex; ++i) {
if(strcmp(users[i].userName,searchName) == 0){
return users[i];
}
}
}
void *connection_handler(void *socket_desc) {
//Get the socket descriptor
char receivedMessage[2000]; //client's message
int readControl;
int parsedItemNumber = 0;
int sock = *((int *) socket_desc);
while ((readControl = recv(sock, receivedMessage, 2000, 0)) > 0) {
char *parsedCommand[50]; //parsedClientMessage
parsedItemNumber = parsing(parsedCommand, receivedMessage, " ");
if (strcmp(parsedCommand[0], "login") == 0) {
loginUser(parsedCommand[1], sock);
}
else if (strcmp(parsedCommand[0], "getusers") == 0) {
getUsers(sock);
}
else if (strcmp(parsedCommand[0], "exit") == 0) {
close(sock);
return 0;
}
else{
if(parsedCommand[0] != NULL){
struct User find = searchUser(parsedCommand[0]);
if(find.userName != NULL){
char *message = malloc(2000);
if(parsedCommand[1] != NULL){
strcpy(message,parsedCommand[1]);
strcat(message," ");
}
for (int i = 2; i < parsedItemNumber; ++i) {
strcat(message,parsedCommand[i]);
strcat(message," ");
}
sendMessage(find,message);
}
else{
perror("Your input was wrong");
}
}
}
}
if (readControl == 0) {
puts("Client disconnected");
clientNumber--;
fflush(stdout);
} else if (readControl == -1) {
perror("recv failed");
}
//Free the socket pointer
free(socket_desc);
return 0;
}
int main(int argc, char *argv[]) {
int socket_desc, new_socket, c, *new_sock;
struct sockaddr_in server, client;
//Create Socket
socket_desc = socket(AF_INET, SOCK_STREAM, 0);
if (socket_desc == -1) {
puts("Could not create socket");
return 1;
}
server.sin_family = AF_INET;
server.sin_addr.s_addr = INADDR_ANY;
server.sin_port = htons(8888);
if (bind(socket_desc, (struct sockaddr *) &server, sizeof(server)) < 0) {
puts("Binding failed");
return 1;
}
listen(socket_desc, 3);
puts("Server started");
c = sizeof(struct sockaddr_in);
while ((new_socket = accept(socket_desc, (struct sockaddr *) &client, (socklen_t *) &c)) &&
clientNumber < MAX_CLIENT_NUMBER) {
pthread_t sniffer_thread[MAX_CLIENT_NUMBER];
new_sock = malloc(1);
*new_sock = new_socket;
if (pthread_create(&sniffer_thread[clientNumber], NULL, connection_handler,
(void *) new_sock) < 0) {
perror("Could not create thread");
return 1;
} else {
clientNumber++;
}
puts("Client connected");
}
if (new_socket < 0) {
perror("accept failed");
return 1;
}
return 0;
}

Resources