I am writing a simple code to test thread pools. I have a client sendin lines of data to server through different ports.
Some threads receive the data, then send them to other threads for processing.
For now, the only processing I am doing is just to write the data into a file.
Here is the code of the worker thread.
void* worker_thread(void* arg){
int i, workerNum;
pthread_t worker_id = pthread_self();
char *ticket = (char*) arg;
char dumpfile[50];
for(i=0;i<10;i++)
if(pthread_equal(worker_id, id_pool[i]))
break;
if(10==i){
pthread_exit(NULL);
}
workerNum = i;
fprintf(stdout, "Worker [%d] busy\n",workerNum);
sprintf(dumpfile, "worker_%d.log",workerNum);
if(strlen(ticket)<4){
fprintf(stdout, "Worker [%d] RELEASED!!\n",workerNum);
poolStatus[workerNum] = 0;
pthread_mutex_unlock(&mutexes[workerNum]);
pthread_exit(NULL);
}
FILE *logFile = fopen(dumpfile, "a+");
// ticket[strlen(ticket)]
fprintf(logFile, "%s\n", ticket);
fclose(logFile);
sleep(workerNum+2);
poolStatus[workerNum] = 0;
fprintf(stdout, "Worker [%d] RELEASED!!\n",workerNum);
pthread_mutex_unlock(&mutexes[workerNum]);
pthread_exit(NULL);
}
The code works when I run through a debugger (GDB, under linux). When I run it simply on the command line, it runs but does not create the files!
Can you please assist?
the complete code:
#include <time.h>
#include <errno.h>
#include <netdb.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>
#include <strings.h>
#include <sys/time.h>
#include <arpa/inet.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#define BUFSIZE 65535
#define NUMWORKERS 10
static pthread_mutex_t mutexes[NUMWORKERS];
pthread_t id_pool[NUMWORKERS], id_servers[6];
int serverports[6] = {22191, 22192, 22193, 7525, 7526, 7527};
char poolStatus[NUMWORKERS] = {0};
void error(char *msg) {
FILE *logFile = fopen("errorlog.log", "a+");
fprintf(logFile, "%s\n", msg);
fclose(logFile);
exit(1);
}
void* serverListener(void* arg);
void* worker_thread(void* arg);
int main(){
int i, t_err[6];
for(i=0; i< NUMWORKERS; i++)
pthread_mutex_init(&mutexes[i],NULL);
for(i=0; i<6; i++){
t_err[i] = pthread_create(&id_servers[i], NULL, serverListener, NULL);
}
pthread_join(id_servers[5], NULL);
return 0;
}
void* serverListener(void* arg){
int parentfd, childfd; // parent socket & child socket
int portno, clientlen; // port number and size of client address
struct sockaddr_in serveraddr;
struct sockaddr_in clientaddr;// server and client addresses
struct hostent *hostp; // client host info
char buf[BUFSIZE]; // message buffer
char *hostaddrp; // dotted decimal host addr string
int optval, n; // flag value for setsockopt and message byte size
unsigned int CLOCKREF, CLOCKCOUNT;
pthread_t id = pthread_self(); // own thread id
int threadNumber, i=0; // thread number linked to ort to listen to.
char dumpfile[50];
for(i=0; i<6; i++) if(pthread_equal(id, id_servers[i])) break;
threadNumber = i;
portno = serverports[threadNumber];
sprintf(dumpfile, "receiver_%d.log",portno);
// socket: create the parent socket
parentfd = socket(AF_INET, SOCK_STREAM, 0);
if (parentfd < 0)
error("ERROR opening socket");
optval = 1;
setsockopt(parentfd, SOL_SOCKET, SO_REUSEADDR, (const void *)&optval , sizeof(int));
// build the server's Internet address
bzero((char *) &serveraddr, sizeof(serveraddr));
serveraddr.sin_family = AF_INET;
// let the system figure out our IP address
serveraddr.sin_addr.s_addr = htonl(INADDR_ANY);
// this is the port we will listen on
serveraddr.sin_port = htons((unsigned short)portno);
// bind: associate the parent socket with a port
if (bind(parentfd, (struct sockaddr *) &serveraddr,
sizeof(serveraddr)) < 0)
error("ERROR on binding");
// listen: make this socket ready to accept connection requests
if (listen(parentfd, 5) < 0) /* allow 5 requests to queue up */
error("ERROR on listen");
// main loop: wait for a connection request
clientlen = sizeof(clientaddr);
while (1) {
// accept: wait for a connection request
childfd = accept(parentfd, (struct sockaddr *) &clientaddr, &clientlen);
if (childfd < 0)
error("ERROR on accept");
// gethostbyaddr: determine who sent the message
hostp = gethostbyaddr((const char *)&clientaddr.sin_addr.s_addr,
sizeof(clientaddr.sin_addr.s_addr), AF_INET);
if (hostp == NULL)
error("ERROR on gethostbyaddr");
hostaddrp = inet_ntoa(clientaddr.sin_addr);
if (hostaddrp == NULL)
error("ERROR on inet_ntoa\n");
fprintf(stdout, "server established connection with %s (%s)\n", hostp->h_name, hostaddrp);
// read: read input string from the client
CLOCKREF = (unsigned int)time(NULL);
int counter = 0;
while(1){
CLOCKCOUNT = (unsigned int)time(NULL) - CLOCKREF;
bzero(buf, BUFSIZE);
n = read(childfd, buf, BUFSIZE);
if (n < 0) error("ERROR reading from socket");
if(0==n) counter++;
if(3<=counter) {
close(childfd);
return;
}
int busyWorker = 1;
i = 0;
while(busyWorker){
if(i>=NUMWORKERS) i = 0;
if(pthread_mutex_trylock(&mutexes[i])==0){ // not locked, can be used
fprintf(stdout, "port [%d] sends to thread [%d]\n", portno, i);
pthread_create(&id_pool[i], NULL, worker_thread, (void*)buf);
busyWorker = 0;
break;
}
i++;
}
}
close(childfd);
}
}
void* worker_thread(void* arg){
int i, workerNum;
pthread_t worker_id = pthread_self();
char *ticket = (char*) arg;
char dumpfile[50];
for(i=0;i<10;i++)
if(pthread_equal(worker_id, id_pool[i]))
break;
if(10==i){
pthread_exit(NULL);
}
workerNum = i;
fprintf(stdout, "Worker [%d] busy\n",workerNum);
sprintf(dumpfile, "worker_%d.log",workerNum);
if(strlen(ticket)<4){
fprintf(stdout, "Worker [%d] RELEASED!!\n",workerNum);
poolStatus[workerNum] = 0;
pthread_mutex_unlock(&mutexes[workerNum]);
pthread_exit(NULL);
}
FILE *logFile = fopen(dumpfile, "a+");
// ticket[strlen(ticket)]
fprintf(logFile, "%s\n", ticket);
fclose(logFile);
sleep(workerNum+2);
poolStatus[workerNum] = 0;
fprintf(stdout, "Worker [%d] RELEASED!!\n",workerNum);
pthread_mutex_unlock(&mutexes[workerNum]);
pthread_exit(NULL);
}
I believe I have found the problem!!
To pass a message from serverListener thread to worker_thread, I used the pointer to buffer used to read from the socket. Problem is, before the worker_thread could process it, the serverListener has reset the value to zero ( bzero(buf, BUFSIZE) ) ! and given the fact that the worker_thread must only write to file when the size is greater than 4, it doesn't write it.
so to solve my problem, I replaced the line:
pthread_create(&id_pool[i], NULL, worker_thread, (void*)buf);
by:
char *msg2send = strdup(buf);
pthread_create(&id_pool[i], NULL, worker_thread, (void*)msg2send);
And it did the trick!!
Still does not really explain why it could create the files in debug mode though...
Related
After the first child thread exits, the process ends in Linux socket.
Please point the error,thanks.
After I close the first client thread, the main process close,too.
I don't know how to modify the code.
The following is my whole codes.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <sys/signal.h>
#include <fcntl.h>
#include <errno.h>
#include <pthread.h>
#define BUF_SIZE 1024
#define CONNECT_INFO 100
#define CLIENT_SIZE 100
int serv_port = 20000;
pthread_mutex_t mutex;
int clintQueue[CLIENT_SIZE];
int front = 0, rear = 0;
void error_handle(char *message);
void *read_func(void *clnt_sock);
int send_message(int socketFd, char *message, int len);
void error_handle(char *message)
{
perror(message);
exit(-1);
}
int send_message(int socketFd, char *message, int len)
{
pthread_mutex_lock(&mutex);
int ret = write(socketFd, message, len);
if (ret <= 0)
{
perror("write error");
}
pthread_mutex_unlock(&mutex);
return ret <= 0 ? 0 : 1;
}
void *read_func(void *arg)
{
// pthread_detach(pthread_self());
int clnt_sock = *(int *)arg;
char buf[BUF_SIZE];
int message_len;
while ((message_len = read(clnt_sock, buf, BUF_SIZE)) != 0)
{
buf[message_len] = 0;
printf("%s", buf);
send_message(clnt_sock, buf, message_len - 1);
memset(buf, 0, BUF_SIZE);
}
pthread_mutex_lock(&mutex);
printf("client %d[queue is %d]log out\n", clnt_sock, clintQueue[front]);
front++;
pthread_mutex_unlock(&mutex);
close(clnt_sock);
return NULL;
}
int main(int argc, char *argv[])
{
char clientInfo[CONNECT_INFO];
int serv_sock, clnt_sock;
socklen_t clnt_addr_len;
pthread_t read_id; //线程id
struct sockaddr_in serv_addr, clnt_addr;
pthread_mutex_init(&mutex, NULL);
serv_sock = socket(PF_INET, SOCK_STREAM, 0);
if (serv_sock < 0)
{
perror("serv_sock create failed!");
}
memset(&serv_addr, 0, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(serv_port);
serv_addr.sin_addr.s_addr = INADDR_ANY;
if (bind(serv_sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0)
{
error_handle("bind fail");
}
else
{
puts("bind success");
}
if (listen(serv_sock, CLIENT_SIZE) < 0)
{
error_handle("listen fail");
}
else
{
puts("listen success");
}
while (1)
{
clnt_addr_len = sizeof(clnt_addr);
clnt_sock = accept(serv_sock, (struct sockaddr *)&clnt_addr, &clnt_addr_len);
if (clnt_sock < 0)
{
puts("clnt_sock < 0");
close(clnt_sock);
}
if (front == (rear + 1) % CLIENT_SIZE)
{
puts("client queue has flowed, connect failed");
close(clnt_sock);
}
else
{
memset(clientInfo, 0, sizeof(clientInfo));
pthread_mutex_lock(&mutex);
clintQueue[rear++] = clnt_sock;
pthread_mutex_unlock(&mutex);
// debug rear
printf("%d\n", rear);
puts("client queue add");
sprintf(clientInfo, "clientInfo[fd:%d, ip:%s, port:%d] has connected!", clnt_sock, inet_ntoa(clnt_addr.sin_addr), ntohs(clnt_addr.sin_port));
puts(clientInfo);
pthread_create(&read_id, NULL, read_func, (void *)&clnt_sock);
pthread_detach(read_id);
printf("thread %ld create success!\n", (pthread_t)read_id);
}
}
close(serv_sock);
pthread_mutex_destroy(&mutex);
return 0;
}
I want to use a main thread to control the connection, and the child threads to handle sending and receiving
On my computer, the application seems to behave fine:
florian#florian-desktop:~$ ./a.out
bind success
listen success
1
client queue add
clientInfo[fd:4, ip:127.0.0.1, port:33730] has connected!
thread 140353384478272 create success!
client 4[queue is 4]log out
2
client queue add
clientInfo[fd:5, ip:127.0.0.1, port:33732] has connected!
thread 140353384478272 create success!
this is a test
client 5[queue is 5]log out
I connected two telnet sessions to the application. I killed the first telnet immediatelly and the second telnet after sending out the message "this is a test".
My Server can handle multiple clients/switches at a time.
My problem is in my switch I believe, I'm trying to send an open message to the the controller. I create the the tcp socket in the switch and then right after I try to send the message to the controller, however when I try to do this, the socket disconnects from the controller and goes into an infinite loop. I'm not sure why this occurs as I'm creating and sending the message outside of my while loop. If I comment where I send the message, the socket stays connected to the controller and I am able to wait for one of a set of file descriptors to become ready to perform I/O, currently I only have the keyboard and the socket. My socket also receives a message from the controller when it's connected "You are connected to the server". In addition since my switch socket disconnects my recv() return error code 107 due to the fact the socket is disconnected.
I'm not sure If I provided too much code to look through but I added comments where I thought my error was occurring in the switch as well as the controller. Greatly appreciated for some help. I didn't add any of my own header files because they are not necessary.
This where I execute the switch. Sends and receive messages here.
#include "switch.h"
#include "openFIFO.h"
#include "packets.h"
#include <stdio.h>
#include <stdlib.h>
#include <strings.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/select.h>
#include <sys/time.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include<poll.h>
#include <signal.h>
void do_switch(int swIport, char *trafficfile,int swJport, int swKport, int IPlow, int IPhigh,char serverAddress[256], unsigned short portNumber){
int switch_sock;
char server_response[256];
struct pollfd pfds[6];
int rval;
/* Switch */
Switch sw;
sw.swJport = swJport;
sw.swIport = swIport;
sw.swKport = swKport;
sw.IPlow = IPlow;
sw.IPhigh = IPhigh;
int switchLength = sizeof(Switch);
// printf("\n\nstruct switchLength: %d\n", switchLength);
// printf("\n\nSwitch Struct: swIport: %d, swJport: %d, swKport: %d,
IPlow: %d, IPhigh: %d\n", sw.swIport, sw.swJport, sw.swKport, sw.IPlow,
sw.IPhigh);
printf("\n\nSwitch created with the following: swIport: %d, trafficfile:
%s, swJport: %d, swKport: %d, IPlow: %d, IPhigh: %d, serverAddress: %s,
portNumber: %d\n", swIport, trafficfile, swJport, swKport, IPlow, IPhigh,
serverAddress, portNumber);
int fifoWrite[2];
int fifoRead[2];
int counter = 0;
char message[20] = "Hello";
/* Create fifos */
if(swJport != -1){
fifoWrite[0] = openWF(swIport,swJport);
fifoRead[0] = openReadFifo(swJport, swIport);
counter = counter + 2;
}
if(swKport != -1){
fifoWrite[1] = openWF(swIport,swKport);
fifoRead[1] = openReadFifo(swKport, swIport);
counter = counter + 2;
}else if(swKport == -1){
fifoWrite[0] = openWF(swIport,swKport);
fifoRead[0] = openReadFifo(swKport, swIport);
counter = counter + 2;
}
printf("fifoWrite[0]: %d\n", fifoWrite[0]);
printf("fifoRead[0]: %d\n", fifoRead[0]);
printf("fifoWrite[1]: %d\n", fifoWrite[1]);
printf("fifoRead[1]: %d\n", fifoRead[1]);
/* Establish connection between the controller and switch */
/* Send a open packet to the controller */
/* Sending a stuct */
//PROBELM HERE BELOW!!!!!!!
switch_sock = CreateTCPClientSocket(portNumber, serverAddress);
if(send(switch_sock, message, sizeof(message), 0) == -1){
fprintf(stderr, "Send() Failed");
}
else{
printf("Open packet is being sent to the controller\n");
}
/* Initialize poll parameters */
//Keyboard
pfds[0].fd = STDIN_FILENO;
pfds[0].events = POLLIN;
// Socket!
pfds[1].fd = switch_sock;
pfds[1].events = POLLIN;
printf("Starting switch............................\n\n");
while(1){
rval = poll(pfds,2,-1);
if(rval == 0){
fprintf(stderr, "Poll timed out. \n");
}if(rval == -1){
fprintf(stderr, "ERROR: poll() failed");
exit(0);
}
/* Check Keyboard */
if(pfds[0].revents & POLLIN && pfds[0].fd == 0){
int a;
char command[1024][256];
int commands;
char buf[256];
commands = read(0, buf, 256);
buf[commands] = '\0';
buf[commands] = '\0';
char *token;
token = strtok(buf, " ");
while(token != NULL){
strcpy(command[a], token);
a++;
token = strtok(NULL, " ");
}
a = 0;
bzero(buf, 256);
if(strcmp(command[0], "list") == 0){
//TODO: Make a print function
printf("print_switch()\n");
}
if(strcmp(command[0], "exit") == 0){
//TODO: Make a print function
printf(" print_switch()\n");
printf("switch-disconnected\n");
close(switch_sock);
exit(0)
}
}
/* Server sent a welcome message */
// Might be PROBELM HERE BELOW when trying to send the initial packet to
controller!!!!!!!
if(pfds[1].revents & POLLIN){
recv(switch_sock, &server_response, sizeof(server_response), 0);
printf("%s\n", server_response);
}
}
}
Creates a TCP Socket for the switch.
int CreateTCPClientSocket( unsigned short port, char *serverAddress){
int sock; /*socket to create */
struct sockaddr_in servAddr; /* Local address */
/* Construct local address structure */
/* Create socket for incoming connections */
if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0){
fprintf(stderr,"ERROR: socket() failed\n");
exit(0);
}
memset(&servAddr, 0, sizeof(servAddr));
servAddr.sin_family = AF_INET;
servAddr.sin_port = htons(port);
servAddr.sin_addr.s_addr = inet_addr(serverAddress);
if(connect(sock, (struct sockaddr *)&servAddr, sizeof(struct sockaddr)) <
0){
printf("Error code: %d\n", errno);
fprintf(stderr, "ERROR: connect() just failed\n");
exit(0);
}
return sock;
}
This is the controller
#include "controller.h"
#include "packets.h"
#include "switch.h"
#include <stdio.h>
#include <stdlib.h>
#include <strings.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/select.h>
#include <sys/time.h>
#include <netinet/in.h>
#include <arpa/inet.h>
void do_controller(int nSwitch, int portNumber){
int controller_sock; /* Socket descriptor for server/controller */
int clnSocket; /*Socket descriptor for clients */
int activity;
int max_sd;
int sd;
int client_socket[nSwitch];
struct sockaddr_in address;
int addrlen;
/* Controller stuff */
Controller cont;
cont.ackCounter = 0;
cont.openCounter = 0;
Switch sw;
char message[256] = "You have reached the server\n";
char recv_message[20];
printf("\n\nController created: nSwitch: %d on portNumber: %d\n", nSwitch, portNumber);
/* Initialise all client_socket[] to 0 so not checked */
for(int i = 0; i < nSwitch; i++){
client_socket[i] = 0;
}
/*Create the server/controller socket */
controller_sock = CreateTCPServerSocket(portNumber);
//addrlen = sizeof(address);
/* Prepare for nonblocking I/O polling/select from the controller socket */
printf("Starting server.........\n\n");
while(1){
/* Zero the socket set and set for server sockets */
/* This must be reset every time select() is called */
/* Add keyboard to descriptor */
/* Add client and controller sockets to set */
FD_ZERO(&sockSet);
FD_SET(STDIN_FILENO, &sockSet);
FD_SET(controller_sock, &sockSet);
max_sd = controller_sock;
//max_sd = 0;
printf("nSwitch: %d\n", nSwitch);
for(int x = 0; x < nSwitch; x++){
sd = client_socket[x];
printf("sd: %d\n\n", sd);
if(sd > 0)
FD_SET(sd, &sockSet);
if(sd > max_sd)
max_sd = sd;
}
printf("max_sd: %d\n", max_sd);
//wait for one of the sockets, timeout is Null,
//so wait indefinitely
activity = select(max_sd + 1, &sockSet, NULL, NULL,NULL);
//printf("Activity: %d\n", activity);
if(activity < 0){
fprintf(stderr, "ERROR: select()\n");
exit(0);
}
/*Check keyboard */
if(FD_ISSET(STDIN_FILENO, &sockSet)){
int a;
char command[1024][256];
int commands;
char buf[256];
commands = read(0, buf, 256);
buf[commands] = '\0';
char *token;
token = strtok(buf, " ");
while(token != NULL){
strcpy(command[a], token);
a++;
token = strtok(NULL, " ");
}
a = 0;
bzero(buf, 256);
if(strcmp(command[0], "list") == 0){
//TODO: Make a print function
print_controller(&cont, nSwitch);
}
if(strcmp(command[0], "exit") == 0){
//TODO: Make a print function
print_controller(&cont, nSwitch);
exit(0);
}
continue;
}
/* Check the incoming FIFOS from the controller an attached switches */
/*If something happened on the controller socket,
then its an incomming connection. Accept new communitcation.Wait for a client to connect.
Recieve packets sent to the controller_sock
*/
if(FD_ISSET(controller_sock, &sockSet)){
clnSocket = AcceptTCPConnection(controller_sock);
if(send(clnSocket, message, sizeof(message), 0) != sizeof(message)){
fprintf(stderr, "Send()");
exit(0);
}
puts("Welcome message sent successfuly");
//PROBELM HERE BELOW!!!!!!! Returns error code 107 because the
socket disconnected.
recv(controller_sock, &recv_message, sizeof(recv_message), 0);
printf("This is my recv_message: %s\n", recv_message);
/*add new socket to array of sockets*/
for(int a = 0; a < nSwitch; a++){
/*if position is empty */
if(client_socket[a] == 0){
client_socket[a] = clnSocket;
printf("Adding to list of sockets as %d\n", client_socket[a]);
break;
}
}
}
/* Communicate with the sockets and handle TCP Client */
for(int z = 0; z <nSwitch; z++){
sd = client_socket[z];
/*Check if it was socket closed, and do other stuff */
if(FD_ISSET(sd ,&sockSet )){
getpeername(sd , (struct sockaddr*)&address , (socklen_t*)&addrlen);
printf("Host disconnected , ip %s , port %d \n" , inet_ntoa(address.sin_addr) , ntohs(address.sin_port));
close( sd );
client_socket[z] = 0;
}else{
//Do stuff for the client
printf("This is the client %d\n", sd);
}
}
}
}
These are the controllers functions: Assign a port to socket,Set socket to listen
int AcceptTCPConnection(int servSock){
int clntSock; /* Socket descriptor for client */
unsigned int clientAddressLen; /* sizeof(client_address); Length of client */
struct sockaddr_in cli_addr; /* Client address */
/* Set the size of the in-out parameter */
clientAddressLen = sizeof(cli_addr);
printf("ClientAddressLen: %x\n", clientAddressLen);
/* Wait for a client to connect */
if ((clntSock = accept(servSock, (struct sockaddr *) &cli_addr,
&clientAddressLen)) < 0){
fprintf(stderr, "ERROR: accept failed\n");
exit(0);
}
/* clntSock is connected to a client! */
//infrom user of socket number used in send and receive commands
printf("Handling client %s\n", inet_ntoa(cli_addr.sin_addr));
printf("New connection: socket fd is: %d, ip is: %s, port: %d\n\n",
clntSock, inet_ntoa(cli_addr.sin_addr), ntohs(cli_addr.sin_port));
return clntSock;
}
Create a TCP socket
int CreateTCPServerSocket(unsigned short port){
int sock; /* socket to create */
struct sockaddr_in servAddr; /* Local address */
/* Create socket for incoming connections */
if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0){
fprintf(stderr,"ERROR: socket() failed\n");
exit(0);
}
/* Construct local address structure */
/* Define the server address */
//bzero((char *) &server_address, sizeof(server_address));
memset(&servAddr, 0, sizeof(servAddr)); /* Zero out structure */
servAddr.sin_family = AF_INET; /* Internet address family
*/
servAddr.sin_addr.s_addr = htonl(INADDR_ANY); /* Any incoming interface
*/
servAddr.sin_port = htons(port); /* Local port */
/* Bind to the local address */
printf("New connection: ip is: %s, port: %d\n\n",
inet_ntoa(servAddr.sin_addr), ntohs(servAddr.sin_port));
if (bind(sock, (struct sockaddr *) &servAddr, sizeof(servAddr)) < 0){
printf("Error code: %d\n", errno);
fprintf(stderr,"ERROR: bind() just failed\n");
exit(0);
}
/* Mark the socket so it will listen for incoming connections */
if (listen(sock, 5) < 0){
fprintf(stderr,"ERROR: listen() failed\n");
exit(0);
}
return sock;
}
I am writing a simple multi-threaded client-server UDP program in C where I send multiple messages at once to the server, and wait for the replies in my receive thread. I'm doing this in order to test the time packets are sent and received.
I have tested locally with my server with 10 packets, and I am correctly receiving all 10 packets, at which point my program terminates.
However, when I test my client with a remote server, my program hangs after I receive about 6 packets. I know the program is hanging on the recvfrom() call, but I don't know why.
I have tried changing the parameters in the call and putting the call in the while loop itself, but to no avail.
Here is my client code:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <pthread.h>
#include <sys/time.h>
#define SERVER_IP "127.0.0.1"
#define PORT 7851
#define DATA_SIZE 99
#define NUM_MSGS 10
// function declaration for connection handler
void *connection_handler(void *);
struct timeval times[NUM_MSGS][2];
struct sockaddr_in serverAddress;
int main() {
int socketFd;
char buf[DATA_SIZE];
//struct sockaddr_in serverAddress;
char msg[DATA_SIZE];
int size, numSent;
time_t timeSent;
pthread_t threadId;
// Create the socket
if ((socketFd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
perror("Socket creation failure");
exit(-1);
}
// Initialize server information
serverAddress.sin_family = AF_INET;
serverAddress.sin_addr.s_addr = inet_addr(SERVER_IP);
serverAddress.sin_port = htons(PORT);
// Print server information
printf("IP address of server is: %s\n", inet_ntoa(serverAddress.sin_addr));
printf("Server port is: %d\n", (int) ntohs(serverAddress.sin_port));
// Create new thread to handle received messages from server
if (pthread_create(&threadId, NULL, connection_handler, (void *)&socketFd) < 0) {
perror("Thread creation failure");
exit(-1);
}
numSent = 0;
int i, j, n;
for (i = 0; i < NUM_MSGS; i++) {
// Get current time and create message
gettimeofday(×[i][0], NULL);
n = snprintf(msg, DATA_SIZE, "%d", numSent);
msg[n] = '\0';
if (n < 0 || n > DATA_SIZE) {
perror("Message creation failure");
}
// Send msg to server
size = sendto(socketFd, (char *)msg, strlen(msg), 0, (struct sockaddr *) &serverAddress, sizeof(serverAddress));
// Check for sendto error
if (size == -1) {
perror("sendto failure");
exit(-1);
}
printf("Client message %d sent.\n", numSent);
numSent++;
}
// Wait for straggler replies
sleep(2);
pthread_join(threadId, NULL);
//print out times
for (i = 0; i < NUM_MSGS; i++){
for (j = 0; j < 2; j++){
printf("[%d][%d] = [%ld.%06ld]\n", i, j, (long int)(times[i][j].tv_sec), (long int)(times[i][j].tv_usec));
}
}
close(socketFd);
return 0;
}
// Connection handler function for new thread created to receive server replies
void *connection_handler(void *newSocketPtr) {
// cast newSocketPtr to integer ptr then dereference to get the socketFd
int socketFd = *(int *)newSocketPtr;
char buf[DATA_SIZE];
int addrLen, size;
int numReceived = 0;
time_t timeSent, timeReceived, diff, totalTime, avgRTT;
addrLen = sizeof(serverAddress);
while ((size = recvfrom(socketFd, (char *)buf, DATA_SIZE, 0, (struct sockaddr *) &serverAddress, &addrLen))!= -1){ // What about when packets get dropped???
printf("Expecting packet %d\n", numReceived+1);
// Check for recvfrom error
if (size == -1){
perror("recvfrom failure");
exit(-1);
}
buf[size] = '\0';
// Get current time
gettimeofday(×[atoi(buf)][1], NULL);
printf("Message received from server: %s\n", buf);
if (numReceived == NUM_MSGS - 1)break;
numReceived++;
printf("num received is %d\n", numReceived);
}
close(socketFd);
pthread_exit(NULL);
}
[...] tested locally with my server with 10 packets [...] test my client with a remote server, my program hangs after I receive about 6 packets.
UDP simply does not guarantee that packets will be delivered. Your remote server was to slow and missed four packets.
I'm working on a TCP client server program which is supposed to support several clients using threads.
The socket creation, connection, bind and accept work as expected since I receive no errors when running the code.
However whenever I try to read() from the server the code enters an infinite loop and nothing happens.
I tried writing from the server first and the write result was written to the server's terminal.
Client code:
#include <stdlib.h>
#include <stdio.h>
#include <stdio.h>
#include <unistd.h>
#include <assert.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <dirent.h>
#define FILE_ADDR "/dev/urandom"
int main(int argc, char *argv[]) {
//Get command line arguments
unsigned int port = atoi(argv[2]);
int length = atoi(argv[3]); //Number of bytes to read
char* buffer = malloc(length * sizeof(char)); //Buffer to hold data read from file
char* recvBuf = malloc(10 * sizeof(char)); // Buffer to hold response from server
struct addrinfo hints, *servinfo, *p;
struct sockaddr_in serv_addr;
int sockfd = -1;
//int rv;
//char ip[100];
memset(&hints, 0, sizeof hints);
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
int rv = getaddrinfo(argv[1], argv[2], &hints, &servinfo);
if (rv != 0) {
perror("getaddrinfo error\n");
exit(1);
}
for (p = servinfo; p != NULL; p = p->ai_next) {
//Initialize socket
sockfd = socket(p->ai_family, p->ai_socktype, p->ai_protocol);
if (sockfd < 0)
continue;
//Initialize connection
rv = connect(sockfd, p->ai_addr, (socklen_t) p->ai_addrlen);
if (rv == 0)
break;
close(sockfd);
sockfd = -1;
}
// inet_aton(ip, &h.sin_addr);
freeaddrinfo(servinfo);
//Open file for reading
FILE *fp;
fp = fopen(FILE_ADDR, "r");
if (fp == NULL) {
perror("Error in file open\n");
}
printf("file opened\n");
size_t numOfbytesRead = fread(buffer, sizeof(char), length, fp);
if (numOfbytesRead != length) {
perror("Error reading from file\n");
}
printf("Buffer is %s\n", buffer);
char* ptr;
unsigned int N = strtoul(argv[3],&ptr,10);
int convertedNum = htonl(N);
if (write(sockfd, &convertedNum, sizeof(unsigned int)) < 0) { //Send number of bytes
perror("error writing to socket");
}
if (write(sockfd, buffer, sizeof(buffer) < 0)) {//Send bytes read from file
perror("error writing to socket");
}
printf("send is done \n");
int bytes_read = read(sockfd, recvBuf, sizeof(recvBuf)); //Recieve response from server
if (bytes_read <= 0) {
perror("Error in recieving result from server\n");
}
unsigned int C = 0;
sprintf(recvBuf[0], "%d", C);
fclose(fp);
printf("# of printable characters: %u\n", C);
exit(0);
free(buffer);
free(recvBuf);
}
Server code:
#include <stdlib.h>
#include <stdio.h>
#include <stdio.h>
#include <unistd.h>
#include <assert.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <dirent.h>
#include <pthread.h>
#include <signal.h>
static volatile int keepRunning = 1;
int pcc_total[159];
void intHandler(int dummy) {
keepRunning = 0;
}
void *compute(void *socket_desc) {
int count = 0;
int sock = *(int*) socket_desc;
printf("now will allocate N \n");
int n=0;
if (write(sock, "hi", 2) < 0) { //Send number of bytes
perror("error writing to socket\n");
}
if (read(sock, &n, sizeof(unsigned int)) < 0) {
perror("Error reading from socket\n");
exit(1);
}
int N = ntohl(n);
printf("len is %d\n", N);
char* data = calloc(N, sizeof(char));
int len = read(sock, data, N);
printf("data is %s\n", data);
if (len < 0) {
perror("Error reading from socket\n");
exit(1);
}
for (int i = 0; i < len; i++) {
int tmp = 0;
sprintf(data[i], "%d", tmp);
if (tmp >= 32 & tmp <= 126) {
count++;
__sync_fetch_and_add(&pcc_total[tmp], 1);
}
}
char scount[100];
atoi(count);
write(sock, count, strlen(scount));
free(data);
pthread_exit(NULL);
close(sock);
exit(0);
}
int main(int argc, char *argv[]) {
unsigned int port = atoi(argv[1]);
signal(SIGINT, intHandler);
int socket_desc, client_sock, c, *new_sock;
struct sockaddr_in server, client;
c = sizeof(struct sockaddr_in);
socket_desc = socket( AF_INET, SOCK_STREAM, 0);
if (socket_desc == -1) {
perror("Could not create socket");
exit(1);
}
printf("socket created\n");
memset(&server, 0, c);
server.sin_family = AF_INET;
server.sin_addr.s_addr = htonl(INADDR_ANY);
server.sin_port = htons(port);
if (0 != bind(socket_desc, (struct sockaddr*) &server, sizeof(server))) {
perror("\n Error : Bind Failed \n");
exit(1);
}
printf("bind created\n");
if (0 != listen(socket_desc, 10)) {
perror("\n Error : Listen Failed \n");
exit(1);
}
printf("listen created\n");
while (keepRunning) {
client_sock = accept(socket_desc, (struct sockaddr *) &client,
(socklen_t*) &c);
if (client_sock < 0) {
perror("\n Error : Accept Failed\n");
exit(1);
}
printf("accept created\n");
pthread_t tid;
new_sock = malloc(100*sizeof(int));
*new_sock = client_sock;
if ((pthread_create(&tid, NULL, compute, (void*) new_sock)) < 0) {
perror("could not create thread\n");
exit(1);
}
printf("thread created\n");
// close socket
close(client_sock);
free(new_sock);
pthread_join(tid, NULL);
}
exit(0);
}
I run the code with the following commands:
gcc -std=c99 -O3 -Wall -o pcc_server pcc_server.c -pthread
gcc -std=gnu99 -O3 -Wall -o pcc_client pcc_client.c
There are a number of problems with your code.
On the client side:
When calling fread(), you need to use "rb" instead of "r".
when calling printf() to output the file data that was actually read, you are not null-terminating buffer, or passing its length to printf(). You need to do so.
You are assigning the return value of htonl() to an int instead of an unsigned int.
when calling write() to send the buffer, you are using sizeof(buffer) when you should be using length or N instead (and why are you using two separate variables to hold the same command-line parameter value?). buffer is a pointer to memory allocated with malloc(), so sizeof(buffer) is the same as sizeof(void*), which is not what you want. Also, you are not even calling write() correctly, because your parenthesis are all wrong (they are correct on the previous write() call when sending convertedNum).
likewise, when calling read() to read the recvBuf, you are using sizeof(recvBuf) when you should be using 10 instead, sicne recvBuf is also a pointer to malloced memory.
you are not reading the "hi" greeting that the server sends to the client upon connection, so you lump in those bytes with the bytes of the following size value of the next message, and thus end up with a corrupted C value.
On the server side:
your compute thread routine sends a "hi" greeting to the client, but it does not use any kind of delimiter, like prefixing the greeting with its length, or terminating it with a line break or null character or other unique character, to separate it from any subsequent data. You should always delimit your messages in some manner.
you are closing the accepted socket and freeing the malloced new_sock as soon as you create a worker thread to handle that client. You are ripping away memory from behind the thread's proverbial back. The thread needs to be the one to close the socket and free the memory when it is done using them, not the accept loop.
The thread does attempt to close the socket (but not free the memory), but after it calls pthread_exit() first, which is wrong. pthread_exit() terminates the calling thread, so it needs to be the last thing that the thread calls (DO NOT call exit()!). In fact, don't even call pthread_exit() directly at all, just return from compute(), the pthreads library will then call pthread_exit() for you, passing it whatever void* value you choose to return.
your accept loop should not be calling pthread_join() at all. It blocks the calling thread until the specified thread terminates. That defeats the whole purpose of using threads to handle your clients, and prevents your server from accepting more than 1 client at a time. If you are going to use pthread_join() at all, it should be after the accept loop has ended, so you can wait for any worker threads that may still be running before exiting the app. But that also means keeping track of the pthread_t values that pthread_create() returns, which is more work.
With that said, try this code instead:
Client code:
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <assert.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <dirent.h>
#define FILE_ADDR "/dev/urandom"
char* readMsg(int sockfd, size_t *msgSize)
{
*msgSize = 0;
unsigned int length = 0;
int bytes_read = read(sockfd, &length, sizeof(length)); //Receive number of bytes
if (bytes_read <= 0) {
perror("Error in receiving message from server\n");
return NULL;
}
length = ntohl(length);
char *buffer = malloc(length+1);
if (!buffer) {
perror("Error in allocating memory to receive message from server\n");
return NULL;
}
char *pbuf = buffer;
unsigned int buflen = length;
while (buflen > 0) {
bytes_read = read(sockfd, pbuf, buflen); // Receive bytes
if (bytes_read <= 0) {
perror("Error in receiving message from server\n");
free(buffer);
return NULL;
}
pbuf += bytes_read;
buflen -= bytes_read;
}
*msgSize = length;
return buffer;
}
int sendMsg(int sockfd, char *msg, size_t msgSize)
{
unsigned int convertedNum = htonl(msgSize);
if (write(sockfd, &convertedNum, sizeof(convertedNum)) < 0) { //Send number of bytes
perror("error writing to socket");
return -1;
}
if (write(sockfd, msg, msgSize) < 0) { //Send bytes
perror("error writing to socket");
return -1;
}
return 0;
}
int main(int argc, char *argv[]) {
char* ptr;
//Get command line arguments
unsigned int port = atoi(argv[2]);
unsigned int length = strtoul(argv[3], &ptr, 10); //Number of bytes to read
char* buffer = malloc(length); //Buffer to hold data read from file
struct addrinfo hints, *servinfo, *p;
struct sockaddr_in serv_addr;
int sockfd = -1;
memset(&hints, 0, sizeof hints);
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
int rv = getaddrinfo(argv[1], argv[2], &hints, &servinfo);
if (rv != 0) {
perror("getaddrinfo error\n");
return 1;
}
for (p = servinfo; p != NULL; p = p->ai_next) {
//Initialize socket
sockfd = socket(p->ai_family, p->ai_socktype, p->ai_protocol);
if (sockfd < 0)
continue;
//Initialize connection
rv = connect(sockfd, p->ai_addr, (socklen_t) p->ai_addrlen);
if (rv == 0)
break;
close(sockfd);
sockfd = -1;
}
freeaddrinfo(servinfo);
if (sockfd == -1) {
perror("socket create/connect error\n");
return 1;
}
size_t msgSize;
char *msg = readMsg(sockfd, &msgSize);
if (!msg) {
close(sockfd);
return 1;
}
printf("%.*s\n", (int)msgSize, msg);
free(msg);
//Open file for reading
FILE *fp = fopen(FILE_ADDR, "rb");
if (fp == NULL) {
perror("Error in file open\n");
close(sockfd);
return 1;
}
printf("file opened\n");
if (fread(buffer, 1, length, fp) != length) {
perror("Error reading from file\n");
fclose(fp);
close(sockfd);
return 1;
}
fclose(fp);
printf("Buffer is %.*s\n", (int)length, buffer);
if (sendMsg(sockfd, buffer, length) != 0) {
free(buffer);
close(sockfd);
return 1;
}
free(buffer);
printf("send is done \n");
msg = readMsg(sockfd, &msgSize); // response from server
if (!msg) {
close(sockfd);
return 1;
}
printf("# of printable characters: %.*s\n", (int)msgSize, msg);
free(msg);
return 0;
}
Server code:
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <assert.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <dirent.h>
#include <pthread.h>
#include <signal.h>
static volatile int keepRunning = 1;
int pcc_total[159];
void intHandler(int dummy) {
keepRunning = 0;
}
char* readMsg(int sockfd, size_t *msgSize)
{
*msgSize = 0;
unsigned int length = 0;
int bytes_read = read(sockfd, &length, sizeof(length)); //Receive number of bytes
if (bytes_read <= 0) {
perror("Error in receiving message from server\n");
return NULL;
}
length = ntohl(length);
char *buffer = malloc(length+1);
if (!buffer) {
perror("Error in allocating memory to receive message from server\n");
return NULL;
}
char *pbuf = buffer;
unsigned int buflen = length;
while (buflen > 0) {
bytes_read = read(sockfd, pbuf, buflen); // Receive bytes
if (bytes_read <= 0) {
perror("Error in receiving message from server\n");
free(buffer);
return NULL;
}
pbuf += bytes_read;
buflen -= bytes_read;
}
*msgSize = length;
return buffer;
}
int sendMsg(int sockfd, char *msg, size_t msgSize)
{
unsigned int convertedNum = htonl(msgSize);
if (write(sockfd, &convertedNum, sizeof(convertedNum)) < 0) { //Send number of bytes
perror("error writing to socket");
return -1;
}
if (write(sockfd, msg, msgSize) < 0) { //Send bytes
perror("error writing to socket");
return -1;
}
return 0;
}
void *compute(void *socket_desc) {
int sock = * (int*) socket_desc;
free(socket_desc);
if (sendMsg(sock, "hi", 2) != 0) {
perror("error writing to socket\n");
close(sock);
return NULL;
}
size_t length = 0;
char *data = readMsg(sock, &length);
if (!msg) {
close(sock);
return NULL;
}
printf("len is %d\n", (int)length);
printf("data is %.*s\n", (int)length, data);
int count = 0;
for (size_t i = 0; i < length; i++) {
// ...
}
free(data);
char scount[20];
sprintf(scount, "%d", count);
sendMsg(sock, scount, strlen(scount));
close(sock);
return NULL;
}
int main(int argc, char *argv[]) {
unsigned int port = atoi(argv[1]);
signal(SIGINT, intHandler);
int socket_desc, client_sock, c, *new_sock;
struct sockaddr_in server, client;
socket_desc = socket( AF_INET, SOCK_STREAM, 0);
if (socket_desc == -1) {
perror("Could not create server socket");
return 1;
}
printf("server socket created\n");
memset(&server, 0, c);
server.sin_family = AF_INET;
server.sin_addr.s_addr = htonl(INADDR_ANY);
server.sin_port = htons(port);
if (bind(socket_desc, (struct sockaddr*) &server, sizeof(server)) < 0) {
perror("\n Error : Bind Failed \n");
close(socket_desc);
return 1;
}
printf("bind created\n");
if (listen(socket_desc, 10) < 0) {
perror("\n Error : Listen Failed \n");
close(socket_desc);
return 1;
}
printf("listening\n");
while (keepRunning) {
c = sizeof(client);
client_sock = accept(socket_desc, (struct sockaddr *) &client,
(socklen_t*) &c);
if (client_sock < 0) {
perror("\n Error : Accept Failed\n");
continue;
}
printf("client accepted\n");
new_sock = malloc(sizeof(int));
if (!new_sock) {
perror("\n Error : Malloc Failed\n");
close(client_sock);
continue;
}
*new_sock = client_sock;
pthread_t tid;
if (pthread_create(&tid, NULL, &compute, new_sock) != 0) {
perror("\n Error : Thread Create Failed\n");
free(new_sock);
close(client_sock);
continue;
}
printf("thread created\n");
}
close(socket_desc);
return 0;
}
I think you should remove the two lines
close(client_sock);
free(new_sock);
in the server code because the newly created thread can't perform on those variables and memory area if it is freed up at such an early point. Can you try the code again without it?
Your server closes the connected socket and frees the memory in which you stored its file handle immediately after launching the thread to handle that connection. You're unlucky that the server only hangs as a result, but you have data races, so formally your program's behavior is undefined.
Since the server isn't going to do anything else until the thread has finished, you might as well move the close() and free() after the pthread_join(). Or, considering that you do join before creating any other threads, how about just calling compute() synchronously instead of creating a new thread for it to run in?
I am trying to read the data from the file /tmp/k on the server side and copying the data to the message and sending to the client side. Here i am able to send the data to the client and display it on the client. But when i am adding header fields in the client and server, client is showing core dump .Can anyone help me with the problem or can propose a better solution to display the data at the client side
Thanks
client.c
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#include <sys/syscall.h>
#include <netdb.h>
#define MAX_SIZE 100000
#define NUM_CLIENT 5
void *connection_handler(void *);
int main(int argc , char *argv[])
{
int sockfd;
long i;
pthread_t sniffer_thread;
printf("memory allocated for the creation of socket \n");
for (i=1; i<=NUM_CLIENT; i++) {
if( pthread_create( &sniffer_thread , NULL , connection_handler , (void *) i) < 0)
{
perror("could not create thread");
return 1;
}
printf("Thread created \n");
sleep(2);
}
pthread_exit(NULL);
return 0;
}
void *connection_handler(void *threadid)
{
struct head
{
float version;
int msg_length;
int header_length;
char msg_type[50];
};
long etid; /*each thread id */
etid = (long)threadid;
pthread_t tid;
tid = pthread_self();
int sockfd , n;
struct sockaddr_in serv_addr;
struct hostent *server;
void *buf;
buf=(struct head *)malloc((sizeof(struct head)));
char sbuff[MAX_SIZE] , rbuff[MAX_SIZE];
if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0){
printf("Failed creating socket\n");
perror("could not create thread");
return 0;
}
memset(&serv_addr, 0 , sizeof (serv_addr));
printf("the bytes of memory area pointed by serv_addr is filled with constant '0' \n");
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(8888);
if (connect(sockfd, (struct sockaddr *)&serv_addr, sizeof (serv_addr)) < 0) {
perror("Failed to connect to server. Error");
return 0;
}
n = read(sockfd,buf,((sizeof(struct head))));
printf("The socket contains %d \n ",n);
if (n < 0)
perror("ERROR reading from socket");
printf("version -->%f \n msg length -->%d \n header length %d \n msg type--> %s \n ",*(float*)buf,*(int*)((unsigned int)buf+sizeof(float)),*(int*)((unsigned int)buf+sizeof(float)+sizeof(int)),(char*)((unsigned int)buf+sizeof(float)+3*sizeof(int)));
printf("Connected successfully client:%ld \n", tid);
printf("before calling pthread_create getpid: %d getpthread_self: %lu tid:%lu\n",getpid(), pthread_self(), syscall(SYS_gettid));
while(1)
{
printf("For thread : %ld\n", etid);
printf("thread id given by kernel: %ld\n", tid);
fgets(sbuff, MAX_SIZE , stdin);
send(sockfd,sbuff,strlen(sbuff),0);
if(recv(sockfd,rbuff,MAX_SIZE,0)==0)
printf("Error");
else
fputs(rbuff,stdout);
bzero(rbuff,MAX_SIZE);
sleep(2);
}
close(sockfd);
return 0;
}
server.c
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#include <sys/syscall.h>
#include<pthread.h> //for threading , link with lpthread
#include <fcntl.h>
#define PROCESSLIST "/tmp/k"
struct head
{
float version;
int msg_length;
int header_length;
char msg_type[50];
};
void *connection_handler(void *);
int main(int argc , char *argv[])
{
int sockfd , new_socket , c , *new_sock;
struct sockaddr_in serv_addr , client;
char *message;
void *msgptr;
struct head * hdptr;
int n;
hdptr=(struct head *)malloc(sizeof(struct head));
msgptr=malloc((sizeof(struct head)));
printf("msgptr1 %u size = %d\n",(unsigned int) msgptr,sizeof(struct head));
((struct head *)msgptr)->version=5.01;
((struct head *)msgptr)->msg_length=1234;
((struct head *)msgptr)->header_length=2;
strcpy((((struct head *)msgptr)->msg_type),"process list, directory list, OS Name and Version");
((struct head *)msgptr)->flag=0;
printf("intialized \n");
printf("version -->%f \n msg length -->%d \n header length %d \n msg type--> %s \n ",*((float *)msgptr),*((int *)((unsigned int)msgptr+sizeof(float))),*((int *)((unsigned int)msgptr+2*sizeof(int))),(char *)((unsigned int)msgptr+3*sizeof(int)));
//Create socket
sockfd = socket(AF_INET , SOCK_STREAM , 0);
if (sockfd == -1)
{
printf("Could not create socket");
}
//Prepare the sockaddr_in structure
server.sin_family = AF_INET;
server.sin_addr.s_addr = INADDR_ANY;
server.sin_port = htons( 8888 );
//Bind
if( bind(sockfd,(struct sockaddr *)&server , sizeof(server)) < 0)
{
puts("bind failed");
return 1;
}
puts("bind done");
//Listen
listen(sockfd , 3);
//Accept and incoming connection
puts("Waiting for incoming connections...");
c = sizeof(struct sockaddr_in);
while( (new_socket = accept(sockfd, (struct sockaddr *)&client, (socklen_t*)&c)) )
{
puts("Connection accepted");
pthread_t sniffer_thread;
new_sock = malloc(1);
*new_sock = new_socket;
if( pthread_create( &sniffer_thread , NULL , connection_handler , (void*) new_sock) < 0)
{
perror("could not create thread");
return 1;
}
puts("Handler assigned");
}
if (new_socket<0)
{
perror("accept failed");
return 1;
}
return 0;
}
/* This will handle connection for each client */
void *connection_handler(void *sockfd)
{
//Get the socket descriptor
int sock = *(int*)sockfd;
int read_size;
char message[100000], client_message[2000];
int fd;
void *buff;
//Receive a message from client
while( (read_size = recv(sock , client_message , 2000 , 0)) > 0 )
{
system ("ps -ef > /tmp/k");
puts("temp file getting created");
fd = open (PROCESSLIST, O_RDONLY);
puts("file open has taken place");
read(fd, buff, sizeof(*buff));
puts("reading the file");
write(sock, buff, 1);
puts("writing to the buffer");
puts("copied data from buffer to message");
//Send the message back to client
send(sock,message,strlen(message),0);
puts("data has been sent");
}
if(read_size == 0)
{
puts("Client disconnected");
fflush(stdout);
}
else if(read_size == -1)
{
perror("recv failed");
}
//Free the socket pointer
free(sockfd);
return 0;
}
The main problem is you have used indirection on an uninitialized pointer.
This
struct hostent *server;
is almost immediately followed by
bcopy(server->whatever
/* ^ this is wrong, because `server' is not initialized */
It's really hard to see that in your mess (sorry I mean, code). You need to organize your code better. And check for errors to make it robust.
Here is a slight improvement on your code, and I also fixed the issue
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#include <sys/syscall.h>
#include <netdb.h>
#define MAX_SIZE 100000
#define NUM_CLIENT 5
void *connection_handler(void *);
int main(int argc , char *argv[])
{
long i;
pthread_t sniffer_thread;
printf("memory allocated for the creation of socket \n");
for (i = 1 ; i <= NUM_CLIENT ; i++) /* Be consistent, either break braces or don't */
{
if (pthread_create(&sniffer_thread , NULL, connection_handler, (void *) &i) < 0)
{
perror("could not create thread");
return 1;
}
printf("Thread created \n");
sleep(2);
}
pthread_exit(NULL);
return 0;
}
void *connection_handler(void *threadid)
{
struct head
{
float version;
int msg_length;
int header_length;
char msg_type[50];
};
long etid; /*each thread id */
pthread_t tid;
int sockfd;
int n;
struct sockaddr_in serv_addr;
struct hostent server;
/* ^ you don't need a pointer */
void *buf;
char sbuff[MAX_SIZE];
char rbuff[MAX_SIZE];
tid = pthread_self();
etid = *(long *) threadid;
buf = malloc((sizeof(struct head)));
if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
{
printf("Failed creating socket\n");
perror("could not create thread");
return 0;
}
memset(&serv_addr, 0 , sizeof (serv_addr));
printf("the bytes of memory area pointed by serv_addr is filled with constant '0' \n");
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(8888);
bcopy((char *) server.h_addr, (char *) &serv_addr.sin_addr.s_addr, server.h_length);
if (connect(sockfd, (struct sockaddr *)&serv_addr, sizeof (serv_addr)) < 0)
{
perror("Failed to connect to server. Error");
return 0;
}
n = read(sockfd,buf,((sizeof(struct head))));
printf("The socket contains %d \n ",n);
if (n < 0)
perror("ERROR reading from socket");
printf(
"version -->%f \n msg length -->%d \n header length %d \n msg type--> %s \n ",
*(float *) buf,
*(int *) ((unsigned int *) buf + sizeof(float)),
*(int *) ((unsigned int *) buf + sizeof(float) + sizeof(int)),
(char *) ((unsigned int *) buf + sizeof(float) + 3 * sizeof(int))
/* ^ you need to cast to a pointer type */
);
printf("Connected successfully client:%ld \n", tid);
printf("before calling pthread_create getpid: %d getpthread_self: %lu tid:%lu\n",
getpid(), pthread_self(), syscall(SYS_gettid));
while (1)
{
printf("For thread : %ld\n", etid);
printf("thread id given by kernel: %ld\n", tid);
fgets(sbuff, MAX_SIZE , stdin);
send(sockfd,sbuff,strlen(sbuff),0);
if(recv(sockfd,rbuff,MAX_SIZE,0)==0)
printf("Error");
else
fputs(rbuff,stdout);
bzero(rbuff,MAX_SIZE);
sleep(2);
}
close(sockfd);
return 0;
}
The server variable is delcared as a pointer, but at the time you dereference it it's not yet pointing to anything.
Since it's uninitialized the behavior is undefined when you dereference it. Also, you should be careful when casting pointers, it's not trivial and you already had mistakes like this
*(int *) ((unsigned int) buf + sizeof(float) + sizeof(int))
You are casting buf to an integer and there is a chance that the conversion truncates the pointer for example on x86_64 platforms. With compiler warnings enabled the compiler would warn about pointer to integer conversion.