send information to forked process with threads - c

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?

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.

How to redirect client program on a new arbitrary port in C

I'm trying to implement a client-server program in C. I want the client to connect to the server on a specific port 5555. After the server accepts the connection, I want the server to send back the arbitrary port to the client. In order to redirect the client to that port where the client can send information. My problem is that the client receives the new port but is unable to connect to the server via that port
The client source code is the following (graham.c):
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <netinet/in.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#define PORT 5555
#define MAX_USERNAME_SIZE 16
#define MAX_FILENAME_SIZE 255
#define BUFFSIZE 1024
char *extract_filename_from_path(char *pathname);
char *extract_filename_from_path(char *pathname)
{
char *last = strrchr(pathname, '/');
return (last != NULL) ? last + 1 : pathname;
}
int main(int argc, char *argv[])
{
int sockfd1, sockfd2, numbytes;
struct sockaddr_in their_addr;
struct hostent *he;
FILE *photo;
char buff[BUFFSIZE];
short status = 1;
// verifier le nombre d'arguments
if (argc != 7)
{
fprintf(stderr, "Compléter sa commande de la façon suivante:\n"
"graham ip_serveur nom_utilisateur_dans_le_pool"
" /chemin/vers/la/photo année mois jour");
return EXIT_FAILURE;
}
if ((he = gethostbyname(argv[1])) == NULL)
{
perror("Client: gethostbyname");
return EXIT_FAILURE;
}
// initialiser le socket 1
if ((sockfd1 = socket(PF_INET, SOCK_STREAM, 0)) == -1)
{
perror("Client: socket");
return EXIT_FAILURE;
}
their_addr.sin_family = AF_INET;
their_addr.sin_port = htons(PORT);
their_addr.sin_addr = *((struct in_addr*)he->h_addr);
memset(&(their_addr.sin_zero), '\0', 8);
if (connect(sockfd1, (struct sockaddr *)&their_addr,
sizeof(struct sockaddr)) == -1)
{
perror("Client: connect 1");
return EXIT_FAILURE;
}
// get port
short int port;
if (recv(sockfd1, &port, sizeof(short int), 0) == -1)
{
perror("Client: recv port");
return EXIT_FAILURE;
}
printf("recieved port: %d\n", ntohs(port));
close(sockfd1);
// changer de port
// initialiser le socket 2
if ((sockfd2 = socket(PF_INET, SOCK_STREAM, 0)) == -1)
{
perror("Client: socket");
return EXIT_FAILURE;
}
their_addr.sin_family = AF_INET;
their_addr.sin_port = port;
their_addr.sin_addr = *((struct in_addr*)he->h_addr);
memset(&(their_addr.sin_zero), '\0', 8);
if (connect(sockfd2, (struct sockaddr *)&their_addr,
sizeof(struct sockaddr)) == -1)
{
perror("Client: connect 2");
return EXIT_FAILURE;
}
// 2) envoyer le nom d'utilisateur
if (send(sockfd2, argv[2], MAX_USERNAME_SIZE, 0) == -1)
{
perror("Client: send username");
return EXIT_FAILURE;
}
// 3) envoyer la date de prise
if (send(sockfd2, argv[4], 5, 0) == -1)
{
perror("Client: send year");
return EXIT_FAILURE;
}
if (send(sockfd2, argv[5], 3, 0) == -1)
{
perror("Client: send month");
return EXIT_FAILURE;
}
if (send(sockfd2, argv[6], 3, 0) == -1)
{
perror("Client: send day");
return EXIT_FAILURE;
}
// 4) envoyer le nom de l'image
if (send(sockfd2, extract_filename_from_path(argv[3]), MAX_FILENAME_SIZE, 0) == -1)
{
perror("Client: send filename");
return EXIT_SUCCESS;
}
// 5) envoyer l'image au client
if ((photo = fopen(argv[3], "r")) == NULL)
{
perror("Client: fopen");
return EXIT_FAILURE;
}
do
{
if ((numbytes = write(sockfd2, buff, BUFFSIZE)) > 0)
{
for (int i = 0; i < numbytes; i++)
{
buff[i] = getc(photo);
}
}
else
{
break;
}
}while(1);
fclose(photo);
// 6) recevoir et traiter le code de retour
if ((numbytes = recv(sockfd2, &status, sizeof(short int), 0)) == -1)
{
perror("Client: recv return code");
return EXIT_FAILURE;
}
if ((status = ntohs(status)))
{
fprintf(stderr, "Echec de la transaction");
}
close(sockfd2);
return EXIT_SUCCESS;
}
the server source code is (spbx.c):
#include "spbx.h"
int my_read(FILE *target, const int source_fd)
{
char buff[BUFFSIZE];
memset(buff, '\0', BUFFSIZE);
int numbytes;
int status = 0;
if ((numbytes = read(source_fd, buff, BUFFSIZE)) > 0)
{
for (int i = 0; i < numbytes; i++)
{
putc(buff[i], target);
}
}
else
{
status = -1;
}
return status;
}
int my_mkdir(const char *path, mode_t mode)
{
struct stat s;
int status = 0;
if (stat(path, &s) == -1)
{
if (mkdir(path, mode) == -1 && errno != EEXIST)
{
status = -1;
}
}
else
{
errno = ENOTDIR;
status = -1;
}
return status;
}
int init_socket(int *sockfd, const short int port)
{
struct sockaddr_in my_addr;
int yes = 1;
if ((*sockfd = socket(PF_INET, SOCK_STREAM, 0)) == -1)
{
perror("Serveur: socket");
return -1;
}
if (setsockopt(*sockfd, SOL_SOCKET,
SO_REUSEADDR, &yes, sizeof(int)) == -1)
{
perror("Serveur: setsockopt");
return -1;
}
my_addr.sin_family = AF_INET;
my_addr.sin_port = htons(port);
my_addr.sin_addr.s_addr = INADDR_ANY;
memset(&(my_addr.sin_zero), '\0', 8);
if (bind(*sockfd, (struct sockaddr *)&my_addr,
sizeof(struct sockaddr)) == -1)
{
perror("Serveur: bind");
return -1;
}
if (listen(*sockfd, BACKLOG) == -1)
{
perror("Serveur: listen");
return -1;
}
return 0;
}
int recv_date(int new_fd, char **year, char **month, char **day)
{
int numbytes;
if ((numbytes = recv(new_fd, year, 5, 0)) == -1)
{
perror("Serveur: recv year");
return -1;
}
if ((numbytes = recv(new_fd, month, 3, 0)) == -1)
{
perror("Serveur: recv month");
return -1;
}
if ((numbytes = recv(new_fd, day, 3, 0)) == -1)
{
perror("Serveur: recv day");
return -1;
}
return 0;
}
int main(int argc, char *argv[])
{
// ecouter sur sockfd et etablir la nouvelle
// connexion sur new_fd
int sockfd1, sockfd2, new_fd, numbytes, photo_tmp_fd;
struct sockaddr_in their_addr;
unsigned int sin_size;
char username[MAX_USERNAME_SIZE];
char filename[MAX_FILENAME_SIZE];
char path_tmp[MAX_FILEPATH_SIZE];
char path[MAX_FILEPATH_SIZE];
memset(path, '\0', MAX_FILEPATH_SIZE);
char year[5], month[3], day[3];
FILE *photo_tmp;
FILE *photo;
short int status = 1;
fd_set readfds;
int max;
// verifier le nombre d'arguments
if (argc != 2)
{
fprintf(stderr, "Donner le chemin vers le pool 2\n");
return EXIT_FAILURE;
}
// initialiser les socket
if(init_socket(&sockfd1, MY_PORT) == -1) return EXIT_FAILURE;
if(init_socket(&sockfd2, 0) == -1) return EXIT_FAILURE;
struct sockaddr_in my_addr;
if (getsockname(sockfd2, (struct sockaddr*)&my_addr, &sin_size) == -1)
{
perror("Serveur: getsockname");
return EXIT_FAILURE;
}
sin_size = sizeof(struct sockaddr_in);
while (1)
{
//initialisation du fd_set
FD_ZERO(&readfds);
FD_SET(sockfd1, &readfds);
FD_SET(sockfd2, &readfds);
max = (sockfd1 < sockfd2)? sockfd2 : sockfd1;
select(max + 1, &readfds, NULL, NULL, NULL);
if (FD_ISSET(sockfd1, &readfds))
{
// on envoie le port
if ((new_fd = accept(sockfd1,
(struct sockaddr *)&their_addr,
&sin_size)) == -1)
{
perror("Serveur: accept 1");
return EXIT_FAILURE;
}
printf("Serveur: connexion reçue du client %s\n",
inet_ntoa(their_addr.sin_addr));
if (fork() == 0)
{
close(sockfd1);
if (send(new_fd, &my_addr.sin_port, sizeof(short int), 0) == -1)
{
perror("Serveur: send port");
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
close(new_fd);
}
else if (FD_ISSET(sockfd2, &readfds))
{
if ((new_fd = accept(sockfd2,
(struct sockaddr *)&their_addr, &sin_size)) == -1)
{
perror("Serveur: accept 2");
return EXIT_FAILURE;
}
printf("Serveur: connexion reçue du client %s redirigé vers le port %d\n",
inet_ntoa(their_addr.sin_addr), ntohs(my_addr.sin_port));
if (fork() == 0)
{
close(sockfd1);
close(sockfd2);
// 2) recevoir l'utilisateur du pool sous forme
// de chaîne de caractères
if ((numbytes = recv(new_fd, &username, MAX_USERNAME_SIZE, 0)) == -1)
{
perror("Serveur: recv username");
return EXIT_FAILURE;
}
// 3) récevoir la date de prise de vue
if(recv_date(new_fd, (char **) &year, (char **)&month, (char **) &day) == -1)
return EXIT_FAILURE;
// 4) recevoir le nom du fichier
if ((numbytes = recv(new_fd, &filename, MAX_FILENAME_SIZE, 0)) == -1)
{
perror("Serveur: recv filename");
return EXIT_FAILURE;
}
// 5) recevoir l'image téléversée par le client
sprintf(path_tmp, "/tmp/%s", filename);
if ((photo_tmp = fopen(path_tmp, "w")) == NULL)
{
perror("Serveur: fopen");
return EXIT_FAILURE;
}
do
{
if (my_read(photo_tmp, sockfd2) == -1) break;
}while(1);
fclose(photo_tmp);
// 6) creer l'arborescence
sprintf(path, "%s/%s", argv[1], username);
my_mkdir(path, MODE);
sprintf(path, "%s/%s/%s", argv[1], username, year);
my_mkdir(path, MODE);
sprintf(path, "%s/%s/%s/%s", argv[1], username, year, month);
my_mkdir(path, MODE);
sprintf(path, "%s/%s/%s/%s/%s", argv[1], username, year, month, day);
my_mkdir(path, MODE);
sprintf(path, "%s/%s/%s/%s/%s/%s", argv[1], username, year, month, day, filename);
// 7) Enregistrement de la photographie
if ((photo = fopen(path, "w")) == NULL
|| (photo_tmp_fd = open(path_tmp, O_WRONLY)) == -1)
{
perror("Serveur: fopen");
return EXIT_FAILURE;
}
do
{
if (my_read(photo, photo_tmp_fd) == -1) break;
}while(1);
close(photo_tmp_fd);
fclose(photo);
// 8) enoyer le code 0 en cas de success
status = htons(0);
if (send(new_fd, &status, sizeof(short int), 0) == -1)
{
perror("Serveur: send code");
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
close(new_fd);//9) deconnexion
}
else
{
fprintf(stderr, "erreur de select\n");
}
}
return EXIT_SUCCESS;
}
I get the following result when I run the server and try two times to connect to it with the client program:
server side:
Serveur: connexion reçue du client 127.0.0.1
Serveur: connexion reçue du client 127.0.0.1
client side:
recieved port: 4645
Client: connect 2: Connection refused
recieved port: 4645
Client: connect 2: Connection refused
The only thing I noticed is that the port stays the same for the same execution of the server and multiple execution of the client. But I don't know what I'm doing wrong. Thanks in advance.
I should have created the new socket after the clients connects as mentioned by
#ChrisTurner. So I moved the following lines:
if(init_socket(&sockfd2, 0) == -1) return EXIT_FAILURE;
if (getsockname(sockfd2, (struct sockaddr*)&my_addr, &sin_size) == -1)
{
perror("Serveur: getsockname");
return EXIT_FAILURE;
}
right after the first accept() and before the fork() in server program.

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;
}

asynchronous socket server, killing thread 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;
}

Resources