Error in Multithreading for client and server programming - c

I am trying to create a client server application whose code I have attached below. I want to use this as a single node for my network which consists of both server and client. This node will be used in future for communicating with other nodes(same code will be run on different machines)
Now I am creating a thread for both client and server functions which should run alternatively through context switching using my own thread library. Following is the code for my client server node
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <arpa/inet.h>
#include <pthread.h>
#include "so.h"
#include <sched.h>
#include <openssl/sha.h>
char s[50];
void *client()
{
int port=5000;
int sockfd = 0,n = 0,i=0;
char recvBuff[1024],sendBuff[1025];
struct sockaddr_in serv_addr;
printf("Inside client\n");
memset(recvBuff, '0' ,sizeof(recvBuff));
while(1){
printf("running client for %dth time\n",i++);
if((sockfd = socket(AF_INET, SOCK_STREAM, 0))< 0)
{
printf("\n Error : Could not create socket \n");
}
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(port);
serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
if(connect(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr))<0)
{
printf("\n Error : Connect Failed \n");
}
else
{
strcpy(sendBuff, "Hi");
send(sockfd, sendBuff, strlen(sendBuff),0);
}
while((n = read(sockfd, recvBuff, sizeof(recvBuff)-1)) > 0)
{
recvBuff[n] = 0;
if(fputs(recvBuff, stdout) == EOF)
{
printf("\n Error : Fputs error");
}
printf("\n");
}
if( n < -1)
{
printf("\n Read Error \n");
}
sleep(1);
close(sockfd);
}
// return 0;
}
void *server( )
{
int port =5000;
printf("Inside server\n");
int listenfd = 0,connfd = 0,n = 0;
struct sockaddr_in serv_addr;
char sendBuff[1025],recvBuff[1024];
int numrv;
listenfd = socket(AF_INET, SOCK_STREAM, 0);
printf("socket retrieve success\n");
memset(&serv_addr, '0', sizeof(serv_addr));
memset(sendBuff, '0', sizeof(sendBuff));
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
serv_addr.sin_port = htons(port);
bind(listenfd, (struct sockaddr*)&serv_addr,sizeof(serv_addr));
if(listen(listenfd, 10) == -1){
printf("Failed to listen\n");
return;
}
printf("Binding done\n");
while(1)
{
connfd = accept(listenfd, (struct sockaddr*)NULL ,NULL); // accept awaiting request
strcpy(sendBuff, "Message from server1");
write(connfd, sendBuff, strlen(sendBuff));
n=recv(connfd, sendBuff, 1024, 0); //if hi received by the client,then server should receive "Message Received" from the client
sendBuff[n]='\0';
printf("%s\n", sendBuff);
close(connfd);
sleep(1);
}
// return 0;
}
int main(int argc,char **argv)
{
printf("Getting IP addr");
char *ip;
struct hostent *HostEntPtr;
struct in_addr in;
char Hostname[100];
gethostname( Hostname, sizeof(Hostname) );
HostEntPtr = gethostbyname( Hostname );
if ( HostEntPtr != NULL )
{
memcpy( &in.s_addr, *HostEntPtr->h_addr_list, sizeof(in.s_addr) );
ip = inet_ntoa(in);
printf( "ip address is %s\n", ip );
}
printf("Running client and server \n");
create(server);
create(client);
start();
while(1);
return 0;
}`
Following is the code for my thread library which uses SIGSETJMP and SIGLONGJMP. File name is so.h
#include <stdio.h>
#include <unistd.h>
#include <signal.h>
#include <setjmp.h>
#include <stdlib.h>
#include <sys/time.h>
#define SECOND 1000000
#define STACK_SIZE 4096
#define QUANTUM 1
void return_function();
struct thread
{
int flag;
int thread_id;
void *arg;
void *ret;
jmp_buf Env;
char stack[STACK_SIZE];
struct thread *next;
void (*func)(void);
void* (*func1)(void*);
}*front_readyqueue,*rear_readyqueue,*current_thread,*temp,*previous;
struct thread *front_created,*rear_created;
#ifdef __x86_64__
typedef unsigned long address_t;
#define JB_BP 1
#define JB_SP 6
#define JB_PC 7
address_t translate_address(address_t addr)
{
address_t ret;
asm volatile("xor %%fs:0x30,%0\n"
"rol $0x11,%0\n"
: "=g" (ret)
: "0" (addr));
return ret;
}
#else
typedef unsigned int address_t;
#define JB_BP 3
#define JB_SP 4
#define JB_PC 5
address_t translate_address(address_t addr)
{
address_t ret;
asm volatile("xor %%gs:0x18,%0\n"
"rol $0x9,%0\n"
: "=g" (ret)
: "0" (addr));
return ret;
}
#endif
int id=0;
int create(void (*f)(void))
{
address_t sp, pc,rt;
temp = (struct thread *)malloc(sizeof(struct thread));
id=id+1;
temp->thread_id=id;
temp->func=f;
sp = (address_t)temp->stack + STACK_SIZE - sizeof(address_t);
pc = (address_t)return_function;
sigsetjmp(temp->Env, 1);
(temp->Env->__jmpbuf)[JB_SP] = translate_address(sp);
(temp->Env->__jmpbuf)[JB_PC] = translate_address(pc);
(temp->Env->__jmpbuf)[JB_BP] = translate_address(rt);
sigemptyset(&temp->Env->__saved_mask);
if (front_readyqueue == NULL)
{
front_readyqueue=temp;
front_readyqueue->next=NULL;
rear_readyqueue=front_readyqueue;
printf("Thread %d created \n",id);
}
else
{
rear_readyqueue->next=temp;
rear_readyqueue=rear_readyqueue->next;
rear_readyqueue->next=front_readyqueue;
printf("Thread %d created \n",id);
}
return id;
}
void dispatch(int sig)
{
int i,j;
struct thread *temp_dispatch;
int ret_val = sigsetjmp(current_thread->Env,1);
printf("SWITCH: ret_val=%d\n", ret_val);
if (ret_val == 1) {
return;
}
current_thread=current_thread->next;
printf("switching to Thread %d \n",current_thread->thread_id);
longjmp(current_thread->Env,1);
}
void alarm_handler(int dummy)
{
alarm(QUANTUM);
signal(SIGALRM, alarm_handler);
dispatch(1);
}
void start()
{
printf("START \n");
long start_time=time(0);
signal(SIGALRM, alarm_handler);
alarm(QUANTUM);
current_thread=front_readyqueue;
siglongjmp(current_thread->Env, 1);
}
void return_function()
{
void *var;
struct thread *temp_rt=current_thread,*temp1,*node;
temp_rt->func();
signal(SIGALRM,SIG_IGN);
alarm(QUANTUM);
signal(SIGALRM, alarm_handler);
dispatch(1);
}
Following is the error dump
Getting IP addrip address is 10.208.20.204
Running client and server
Thread 1 created
Thread 2 created
START
Inside server
socket retrieve success
Binding done
SWITCH: ret_val=0
switching to Thread 2
Inside client
running client for 0th time
SWITCH: ret_val=0
switching to Thread 0
Segmentation fault (core dumped)
PS: When I try to create a thread on normal functions which does not use any blocking call then switching is taking place perfectly fine. I think that switching problem that I am facing is because of blocking calls used in server and client function. Any help would be appreciated. Thanks in advance

Related

After the first child thread exits, the process ends in Linux socket

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".

program received signal sigsegv segmentation fault on using a pointer of a struct pointing to a structure placed on a shared memory

#include <stdio.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <stdbool.h>
#define PORT 8080
#define SHM_SIZE 1024*(512+4)+100*((4*2)+(1024*2))+(4*4)
//---modes-----//
#define NOAUTO "NOAUTO"
#define AUTO "AUTO"
//---commands---//
#define SEND "SEND"
#define FETCH "FETCH"
#define FETCHIF "FETCHIF"
#define QUIT "QUIT"
#define EOF2 "EOF"
typedef char message[512];
typedef struct {
bool is_active;
int start_index;
int end_index;
bool indices[1024];
}circular_queue;
typedef struct {
message message_list[1024];
int last_index;
circular_queue connections[100];
int last_conn_index;
int remained_read[1024];
int num_conn;
int queue_start;
}multicast_queue;
int main(int argc, char const *argv[])
{
//-------------------connect to server-----------------//
int sock = 0, valread;
struct sockaddr_in serv_addr;
char *hello = "Hello from client";
char shmid_s[512] = {0};
if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0)
{
printf("\n Socket creation error \n");
return -1;
}
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(PORT);
// Convert IPv4 and IPv6 addresses from text to binary form
if(inet_pton(AF_INET, "127.0.0.1", &serv_addr.sin_addr)<=0)
{
printf("\nInvalid address/ Address not supported \n");
return -1;
}
if (connect(sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0)
{
printf("\nConnection Failed \n");
return -1;
}
read( sock , shmid_s, 512); //-----read shared memory information over socket-----//
int shmid = atoi(shmid_s);
printf("%d\n",shmid );
//---------------------attach to shared memory---------------------------//
if(shmid == -1)
{
perror("shmget");
exit(1);
}
multicast_queue *multicast_queue = shmat(shmid, (void*)0, 0);
if(multicast_queue == (void*)(-1))
{
perror("shmat");
exit(1);
}
int conn_no=multicast_queue->last_conn_index;
int read_index=multicast_queue->queue_start;
char *mode = NOAUTO;
printf("%s\n",mode);
char command[7];
memset(command,0,7);
message messagebody;
while(scanf("%s",command))
{
if(!strcmp(command,SEND))
{
printf("Enter the message to send: ");
scanf("%s", messagebody);
printf("%s %s\n", command, messagebody);
}
else if(!strcmp(command,FETCH))
{
message f_message;
memcpy(f_message, multicast_queue->message_list[read_index],512);
multicast_queue->remained_read[read_index]--;
if(multicast_queue->remained_read[read_index] == 0)
{
multicast_queue->queue_start = (multicast_queue->queue_start+1)%1024;
multicast_queue->connections[conn_no].start_index = (multicast_queue->connections[conn_no].start_index+1)%1024;
}
read_index++;
printf("%s\n", f_message);
}
}
return 0;
}
This is a client code piece of a UNIX domain stream socket project. The shared memory is created by the server code and shmid is send through the socket. Then, to use the shared memory, a pointer of the same type with the constructed data structure over the shared memory is set. Using this pointer the shared memory is attached to this client process. I get a segmentation error whenever i try to access a member of the multicast_queue which is attached to the shared memory (int conn_no=multicast_queue->last_conn_index;). I run this program on a virtual machine Ubuntu. I don't know what the reason behind getting this error is. I also increased the memory size for Ubuntu but it didn't work.

recvfrom is not receiving any data, but client is sending the message successfully

I have client-server program where I created the socket with sctp protocol and client and server has a onetomany relation.
when I run the client code the return value of sendto function is greater than zero. But I don't see any message in the server code output.
Even when the server code is not running and only the client code is running, the client code shows successful message sent. How can it be when the server sockeet is not even open?
/*
* Compile:
*
* gcc sctp.c -o server -lsctp
*
* Invoke:
*
* ./client
* ./server
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <libgen.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <netinet/sctp.h>
#include <arpa/inet.h>
#define MY_PORT_NUM 21233
static void die(const char *s) {
perror(s);
exit(1);
}
static void server(void) {
int listen_fd, conn_fd, flags, ret, in;
struct sctp_sndrcvinfo sndrcvinfo;
struct sockaddr_in servaddr = {
.sin_family = AF_INET,
.sin_addr.s_addr = htonl(INADDR_ANY),
.sin_port = htons(MY_PORT_NUM),
};
struct sockaddr_in client_addr;
socklen_t clilen=sizeof(client_addr);
struct sctp_initmsg initmsg = {
.sinit_num_ostreams = 5,
.sinit_max_instreams = 5,
.sinit_max_attempts = 4,
};
listen_fd = socket(AF_INET, SOCK_SEQPACKET, IPPROTO_SCTP);
if (listen_fd < 0)
die("socket");
ret = bind(listen_fd, (struct sockaddr *) &servaddr, sizeof(servaddr));
if (ret < 0)
die("bind");
ret = listen(listen_fd, initmsg.sinit_max_instreams);
if (ret < 0)
die("listen");
for (;;) {
char buffer[1024];
printf("Waiting for connection\n");
in = recvfrom(listen_fd, buffer, sizeof(buffer),0,(struct sockaddr*)&client_addr,&clilen);
printf("%d\n",in);
if (in > 0) {
printf("Received data: %s\n", buffer);
fflush(stdout);
}
sleep(2);
}
close(listen_fd);
}
static void client(void) {
int conn_fd, ret;
const char *msg = "Hello, Server!";
struct sockaddr_in servaddr = {
.sin_family = AF_INET,
.sin_port = htons(MY_PORT_NUM),
.sin_addr.s_addr = inet_addr("127.0.0.1"),
};
conn_fd = socket(AF_INET, SOCK_SEQPACKET, IPPROTO_SCTP);
if (conn_fd < 0)
die("socket()");
int i;
for(i=0;i<4;i++){
printf("before sending\n");
ret = sendto(conn_fd, (void *) msg, strlen(msg) + 1,0,(struct sockaddr*)&servaddr,sizeof(struct sockaddr));
printf("after sending\n");
if (ret < 0)
printf("failed to send %d\n",i);
else
printf("success %d\n",i);
sleep(2);
}
close(conn_fd);
}
int main(int argc, char **argv) {
if (strstr(basename(argv[0]), "server"))
server();
else
client();
return 0;
}
this code works when I run the client and server in same machine with loopback IP 127.0.0.1 but when I run them on two different remote machines I am facing this issue.

SIGIO never fires

ioctl() with changes a socket to asynchronous mode. By the definition on the man page, the kernel sends SIGIO when i/o is possible on the socket. I've run this with test clients and i/o is fine (packets arrive at source and destination), so why wouldn't the kernel call sigpoll?
To clarify, the problem is that despite having established the SIGIO signal and appropriating the socket to send the signal SIGIO, no signal ever fires or there is no indication that sigpoll() was called.
I've uploaded the code where I've found this issue, it will eventually be some watered down version of talk.
talkish.c
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <netdb.h>
#include <signal.h>
#include <setjmp.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#include <sys/param.h>
#include <sys/signal.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <netinet/tcp.h>
#include <netinet/ip.h>
#include <netinet/ip_icmp.h>
#include <netinet/in.h>
#define MAX_BUF 1000
#define CHAR_BUF 50
#define BASEPORT "10000"
void error(const char *msg){
perror(msg);
exit(1);
}
typedef struct tuple{
char HN [MAX_BUF];
char PN [MAX_BUF];
}tuple;
tuple storeCMD( char input[]){
tuple ret;
char* token = strtok(input, " ");
if (token != NULL) strcpy( ret.HN, token);
else ret.HN[0] = 0;
token = strtok(NULL, " ");
if (token != NULL) strcpy( ret.PN, token);
else ret.PN[0] = 0;
return ret;
}
void sigpoll(int sig){
printf("Signal fired!\n");
//eventual rcvfrom and other things...
}
int main(int argc, char * argv[]){
if (argc != 2){
printf("Proper usage requires 2 arguments: $talkish port-number\n");
exit(1);
}
int sd;
struct sockaddr_storage client;
socklen_t clientLen;
struct addrinfo server, *res;
struct addrinfo *serverinfo;
char buffer [MAX_BUF];
memset(&server, 0, sizeof(server));
bzero((char *) &server, sizeof(server));
server.ai_family = AF_INET;
server.ai_socktype = SOCK_DGRAM;
server.ai_flags = AI_PASSIVE;
//initially we'll use information from user, but move to partner and partnerl
//once solid connection is established.
struct sockaddr_storage partner;
socklen_t partnerl;
//Bind to argv[1]
tuple execute;
getaddrinfo(NULL, argv[1], &server, &res);
sd = socket(res -> ai_family ,res -> ai_socktype, res -> ai_protocol);
if (sd < 0) error("ERROR on socket!");
int n = bind(sd, res -> ai_addr, res -> ai_addrlen);
if (n < 0) error("ERROR on Bind!");
int flag;
flag= 1;
fcntl(sd, F_SETOWN, getpid());
signal(SIGPOLL, sigpoll); //establish sigpoll to get udp packets
ioctl(sd, FIOASYNC, &flag);
//establish timer to allow wait and see
struct timeval timer;
timer.tv_sec = 7;
//while connecting
char message[CHAR_BUF];
bzero((char *) message, CHAR_BUF);
int connecting = 1;
while(connecting){
printf ("? ");
scanf(" %[^\n]", message);
if (strlen(message) == 0);
else if ( 0 == strcmp( message, "q")){
exit (0);
}
else {
execute = storeCMD(message);
if (execute.HN[0] == 0 || execute.PN[0] == 0) printf("| Input should match \"Hostname Portname\" to connect and \"q\" to quit \n");
else {
struct sockaddr_storage dest_server;
socklen_t dest_serverl;
struct addrinfo dest_hints, *dest_res;
struct in_addr dest_addr;
memset(&dest_hints, 0, sizeof(dest_hints));
dest_hints.ai_family = AF_INET;
dest_hints.ai_socktype = SOCK_DGRAM;
dest_hints.ai_flags = AI_PASSIVE;
if (getaddrinfo( execute.HN, execute.PN, &dest_hints, &dest_res) < 0) printf("| Input should match \"Hostname Portname\" to connect and \"q\" to quit \n");
else {
bzero((char *) buffer, MAX_BUF);
sprintf(buffer, "wannachat");
sendto(sd, buffer, MAX_BUF, 0, (struct sockaddr *) dest_res -> ai_addr, dest_res -> ai_addrlen );
if (setsockopt(sd, SOL_SOCKET, SO_RCVTIMEO, &timer, sizeof(timer)) < 0) error("ERROR on setsockopt");
partnerl = sizeof(partner);
bzero((char *) &partner, partnerl);
bzero((char *) buffer, MAX_BUF);
if (recvfrom(sd, buffer, MAX_BUF, 0, (struct sockaddr *)&partner, &partnerl ) < 0) printf("| No response received from %s. \n", execute.HN);
else{
if ( 0 == strcmp( buffer, "OK")){
printf("| Connected to %s. \n", execute.HN);
//chat();
}else printf("| %s does not want to talk. \n", execute.HN);
}
}
}
}
}
close(sd);
return 0;
}
To receive SIGIO notifications (also SIGURG for sockets, e.g: when receiving TCP URG data), you'll need to tell the kernel who to notify, using fcntl(fd, F_SETOWN, pid). As usual, a positive pid value refers to a process, while a negative pid refers to a process group.
On Linux, if you want to send the signal to a specific thread, you'll need to use F_SETOWN_EX. On other systems, you'll have to block the signal on other threads. using pthread_sigmask().

Posix server-client application gets stucked during communication

I'm learning C in posix standard. I'm trying to create client-server application, and right now I try to handle communication between them.
I didn't know how to properly let client know when he is supposed to send something to server. What I came up with is simple - when server sends message "1" it means it now waits for client's input.
I first tried with telnet and it somehow worked. Problems came when I created client application - it worked ONCE. And later it decided to stop working. Server properly gets one input from client (when he chooses "AddObject" option) and later it stops working (client doesn't know server waits for a message).
I've tried to clean up my code as much as possible (my actual code is a huge, since I often try different things and have a lot of comments), but it sill probably sucks - sorry for that.
server
#define _GNU_SOURCE
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <sys/syscall.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <errno.h>
#include <string.h>
#include <pthread.h>
#include <stdbool.h>
#include <poll.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <limits.h>
#include <ctype.h>
#define maxnamel 50
#define BUFLEN 512
#define ERR(source) (fprintf(stderr,"%s:%d\n",__FILE__,__LINE__),\
perror(source),kill(0,SIGKILL),\
exit(EXIT_FAILURE))
struct arg_struct {
int fd;
int org;
};
void usage(void);
int make_socket(uint16_t port);
void usage(void){
fprintf(stderr, "Usage: ./all\n");
exit(EXIT_FAILURE);
}
void sendAndPrint(char* wiadomosc, int sock){
write((int)sock , wiadomosc , strlen(wiadomosc));
printf("%s",wiadomosc);
}
int make_socket(uint16_t port) {
struct sockaddr_in name;
int sock, t=1;
sock = socket(PF_INET,SOCK_STREAM,0);
if (sock < 0) ERR("socket");
name.sin_family = AF_INET;
name.sin_port = htons(port);
name.sin_addr.s_addr = htonl(INADDR_ANY);
if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &t, sizeof(t))) ERR("setsockopt");
if (bind(sock,(struct sockaddr*) &name, sizeof(name)) < 0) ERR("bind");
return sock;
}
void addObject (int sock)
{
int read_size, read_size_sum;
char* buf;
char *record;
record=malloc(sizeof(char)*100+1);
buf=malloc(sizeof(char)*10+1);
sendAndPrint("AddObject.\n", sock);
sendAndPrint("Add details of new object.\n", sock);
sendAndPrint("Name:\n", sock);
sleep(0.5);
sendAndPrint("1", sock);
read_size = recv(sock, buf, maxnamel, 0);
printf("%s", buf);
read_size-=1;
buf[read_size]=0;
read_size_sum = read_size;
strcpy(record,buf);
record[read_size-1]=0;
sendAndPrint("Age:\n", sock);
sendAndPrint("1\n", sock);
read_size = recv(sock, buf, 10, 0);
read_size-=1;
buf[read_size+1]=0;
read_size_sum +=read_size;
strcat(record,"-");
strcat(record,buf);
record[read_size_sum-2]=0;
sendAndPrint("Weight:\n", sock);
sendAndPrint("1", sock);
read_size = recv(sock, buf, 10, 0);
buf[read_size-1]=0;
read_size_sum +=read_size;
strcat(record,"-");
strcat(record,buf);
record[read_size_sum-3]=0;
sendAndPrint("Number:\n", sock);
sendAndPrint("1", sock);
read_size = recv(sock, buf, 10, 0);
buf[read_size-1]=0;
read_size_sum +=read_size;
strcat(record,"-");
strcat(record,buf);
record[read_size_sum-3]=0;
strcat(record,"-0");
strcat(record,"\n");
}
void *connection_handler(void *sock_desc)
{
return 0;
}
void *organizer_handler(void *sock_desc)
{
int wybor, read_size;
char client_message[1000];
int sock = *(int*)sock_desc;
sendAndPrint("Start.\n",sock);
sendAndPrint("Choose your action:\n\n1 - Add Object\n2 - To Do\n3 - To Do\n",sock);
sendAndPrint("4 - To Do\n\n\n", sock);
sendAndPrint("1", sock);
while((read_size = recv(sock , client_message , 100 , 0)) > 0 )
{
wybor=atoi(client_message);
if((wybor==1))
addObject(sock);
else
{
sendAndPrint("Wrong choice.\n\n",sock);
sleep(3);
}
sendAndPrint("Choose your action:\n\n1 - Add Object\n2 - To Do\n3 - To Do\n",sock);
sendAndPrint("4 - To Do\n\n\n", sock);
}
return 0;
}
void *doClient(void *arguments){
struct arg_struct *args = arguments;
int fd = args -> fd;
int org = args -> org;
int backlog=10;
int l, c,client_sock, *new_sock;
fd_set set;
pthread_t sniffer_thread2;
struct sockaddr_in client;
l=listen(fd, backlog);
c = sizeof(struct sockaddr_in);
puts("Thread created.");
while(1)
{
FD_ZERO(&set);
FD_SET (fd, &set);
puts("Waiting for connection...");
while((client_sock = accept(fd, (struct sockaddr *)&client, (socklen_t*)&c)))
{
new_sock = malloc(1);
*new_sock = client_sock;
if (org == 1)
{
puts("Organizer has connected. Creating thread...");
if( pthread_create( &sniffer_thread2 , NULL , organizer_handler , (void*) new_sock) < 0)
{
perror("Could not create thread for organizer.");
return 0;
}
} else
{
puts("Normal client has connected. Creating thread...");
if( pthread_create( &sniffer_thread2 , NULL , connection_handler , (void*) new_sock) < 0)
{
perror("Could not create thread for normal client.");
return 0;
}
}
}
}
return 0;
}
void doServer(int fd){
pthread_t sniffer_thread;
char message[1000];
struct arg_struct orgArgs;
orgArgs.fd = fd;
orgArgs.org = 1;
puts("Started server.");
puts("Creating a thread for organizer client...");
if( pthread_create( &sniffer_thread , NULL , doClient , (void *)&orgArgs) < 0)
{
perror("Could not create thread for doClient for organizers.");
return;
}
puts("Type 1 if you want to stop server.");
while (scanf("%s", message))
{
if(atoi(message) == 1)
{
puts("Closing server.");
break;
}
else
puts("Type 1 if you want to stop server.");
}
}
int main(int argc, char** argv) {
int fd;
uint16_t port=8089;
if(argc != 1){
usage();
}
fd = make_socket(port);
doServer(fd);
return EXIT_SUCCESS;
}
client
#define _GNU_SOURCE
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <sys/syscall.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <errno.h>
#include <string.h>
#include <pthread.h>
#include <stdbool.h>
#include <poll.h>
#include <netdb.h>
#define HERR(source) (fprintf(stderr,"%s(%d) at %s:%d\n",source,h_errno,__FILE__,__LINE__),\
exit(EXIT_FAILURE))
#define BUFLEN 512
#define ERR(source) (fprintf(stderr,"%s:%d\n",__FILE__,__LINE__),\
perror(source),kill(0,SIGKILL),\
exit(EXIT_FAILURE))
int fd;
int make_socket(void){
int sock;
sock = socket(PF_INET,SOCK_STREAM,0);
if(sock < 0) ERR("socket");
return sock;
}
struct sockaddr_in make_address(uint16_t port){
struct sockaddr_in addr;
struct hostent *hostinfo;
addr.sin_family = AF_INET;
addr.sin_port = htons (port);
hostinfo = gethostbyname("localhost");
if(hostinfo == NULL)HERR("gethostbyname");
addr.sin_addr = *(struct in_addr*) hostinfo->h_addr;
return addr;
}
int connect_socket(uint16_t port){
struct sockaddr_in addr;
int socketfd;
socketfd = make_socket();
addr=make_address(port);
if(connect(socketfd,(struct sockaddr*) &addr,sizeof(struct sockaddr_in)) < 0){
if(errno!=EINTR) ERR("connect");
else {
fd_set wfds;
int status;
socklen_t size = sizeof(int);
FD_ZERO(&wfds);
FD_SET(socketfd, &wfds);
if(TEMP_FAILURE_RETRY(select(socketfd+1,NULL,&wfds,NULL,NULL))<0) ERR("select");
if(getsockopt(socketfd,SOL_SOCKET,SO_ERROR,&status,&size)<0) ERR("getsockopt");
if(0!=status) ERR("connect");
}
}
return socketfd;
}
void doClientORG(int fd){
int read_size;
int msg_size;
char client_message[1000];
char message[1000];
puts("Waiting for server.");
while((read_size = recv(fd , client_message , 100 , 0)) > 0 )
{
client_message[read_size]=0;
if(atoi(client_message) == 1)
{
puts("Inside");
scanf("%s", message);
/*printf("Message: %s\n\n", message);*/
write(fd, message,1);
}
else
printf("%s", client_message);
}
}
int main(int argc, char** argv) {
int fd;
uint16_t port=8089;
char* message;
fd=connect_socket(port);
doClientORG(fd);
return EXIT_SUCCESS;
}
Any ideas? Did I do something wrong, or is my idea incorrect to begin with?

Resources