Sockets and threads in C - c

I am having a small problem when trying to implement a client-server program with multithreading on the side of the server. My idea is to have the server spin forever, accept a client when it can, and just send it to a client_handle() function using a thread.
Here is the problem: my server and client are using the code seen below. At the point of the initial response of the server, it fails in sending ALL_GOOD_CD. I'm not sure why this is happening, as I print out the socket fd of the client in a line before and it seems to match up with the file descriptor given to us at the time of acception.
One thought is that my socket id is not being passed to the thread correctly. My client never seems to receive the ALL_GOOD_CD (it is blocking on a recv() call after connecting with the server). I am new with threads and sockets, anything would help; thanks!
Here is the client code needed to run:
#include <stdio.h> /* for printf() and fprintf() */
#include <sys/socket.h> /* for socket(), connect(), send(), and recv() */
#include <arpa/inet.h> /* for sockaddr_in and inet_addr() */
#include <stdlib.h> /* for atoi() and exit() */
#include <string.h> /* for memset() */
#include <unistd.h> /* for close() */
void DieWithError(char *errorMessage); /* Error handling function */
int main(int argc, char *argv[])
{
int sock; /* Socket descriptor */
struct sockaddr_in server_addr; /* Server address */
unsigned short server_port; /* Server port */
char *server_ip; /* Server IP address (dotted quad) */
char server_response[300]; /* Buffer to hold response from the server */
char* username;
/* Test for correct number of arguments */
if (argc != 4) {
fprintf(stderr, "Usage: %s <server_ip> <server_port> <username>\n", argv[0]);
exit(1);
}
server_ip = argv[1]; /* Second arg: server IP address (dotted quad) */
server_port = atoi(argv[2]); /* Third arg: server port number */
username = argv[3]; /* Fourth arg: username */
/* Create a reliable, stream socket using TCP */
if ((sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
DieWithError("socket() failed");
/* Construct the server address structure */
memset(&server_addr, 0, sizeof(server_addr)); /* Zero out structure */
server_addr.sin_family = AF_INET; /* Internet address family */
server_addr.sin_addr.s_addr = inet_addr(server_ip); /* Server IP address */
server_addr.sin_port = htons(server_port); /* Server port */
/* Establish the connection to the server */
if (connect(sock, (struct sockaddr*) &server_addr, sizeof(server_addr)) < 0)
DieWithError("connect() failed, could not find server.");
printf("connected\n");
memset(&server_response, 0, 300);
if (recv(sock, server_response, 300, 0) < 0)
DieWithError("recv() for initial response failed");
printf("received initial reponse\n");
}
void DieWithError(char* errorMessage) {
fprintf(stderr, "Dying with error sadface: %s\n", errorMessage);
exit(1);
}
Here is the server code as minified as possible:
#include <stdio.h> /* for printf() and fprintf() */
#include <sys/socket.h> /* for socket(), connect(), send(), and recv() */
#include <arpa/inet.h> /* for sockaddr_in and inet_addr() */
#include <stdlib.h> /* for atoi() and exit() */
#include <string.h> /* for memset() */
#include <unistd.h> /* for close() */
#include <pthread.h> /* multithreading the clients! */
#define MAXMSGSIZE 150
#define MAXCLIENTS 5
#define TOO_MANY_CD 0
#define ALL_GOOD_CD 1
#define OTHER_BAD_CD 2
struct client {
char* username;
char** subs;
int socket;
char temp_msg[MAXMSGSIZE*2];
};
void DieWithError(char* errorMessage); /* Error handling function */
void handle_client(void* new_socket); /* Client handling function */
static struct client** clients;
static pthread_t* threads;
static pthread_mutex_t clients_mutex;
static pthread_mutex_t threads_mutex;
int main(int argc, char *argv[])
{
int server_sock; /* Server socket descriptor */
unsigned short server_port; /* Echo server port */
struct sockaddr_in server_addr; /* sockaddr_in struct to hold information about the server */
int server_addr_size; /* Size of server_addr struct in bytes */
int client_sock;
int empty_thread;
pthread_attr_t thread_attr;
if (argc != 2) { /* Test for correct number of arguments */
fprintf(stderr, "Usage: %s <server_port>\n", argv[0]);
exit(1);
}
clients = (struct client**) calloc(1, sizeof(struct client*) * MAXCLIENTS);
if (clients == NULL)
DieWithError("calloc() for clients failed");
threads = (pthread_t*) calloc(1, sizeof(pthread_t) * MAXCLIENTS);
if (clients == NULL)
DieWithError("calloc() for clients failed");
pthread_mutex_init(&clients_mutex, NULL);
pthread_mutex_init(&threads_mutex, NULL);
pthread_attr_init(&thread_attr);
pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_DETACHED);
server_port = atoi(argv[1]);
/* Create a reliable, stream socket using TCP */
if ((server_sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
DieWithError("socket() failed");
// Zero out server_addr var and fill with information
memset(&server_addr, 0, sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
server_addr.sin_port = htons(server_port);
// Bind server with sock, IP, and port so that the clients can connect to us
if (bind(server_sock, (struct sockaddr*) &server_addr, sizeof(server_addr)) < 0)
DieWithError("bind() failed");
// Allow this server to accept 5 clients at a time (queue has 0 capacity because we multithread)
if (listen(server_sock, 0) < 0)
DieWithError("listen() failed");
// Display some information so we can connect with client
printf("Using\n\tport: %d\n\tIP: %s\n", server_port, inet_ntoa(server_addr.sin_addr));
server_addr_size = sizeof(server_addr);
for (;;) {
int* new_socket = (int*)malloc(sizeof(int));
if ((*new_socket = accept(server_sock,
(struct sockaddr*) &server_addr, &server_addr_size)) < 0) {
printf("accept() failed");
continue;
}
int free_spot = -1;
for (int i = 0; i < MAXCLIENTS; i++)
if (!threads[i]) free_spot = i;
if (free_spot == -1) {
printf("no empty threads (max clients handled currently)");
send(*new_socket,(void*) OTHER_BAD_CD, sizeof(OTHER_BAD_CD), 0);
close(*new_socket);
continue;
}
if (pthread_create(&threads[free_spot], &thread_attr,
(void*) &handle_client, (void*) new_socket)) {
printf("pthread_create failed");
close(*new_socket);
continue;
}
printf("sent new client %d to handle_client()\n", *new_socket);
}
}
void handle_client(void* new_socket) {
int socket = *(int*)new_socket;
free(new_socket);
printf("handling new client %d\n", socket);
struct client* curr_cl;
pthread_mutex_lock(&clients_mutex);
printf("locked mutex?\n");
if (send(socket, (void*)ALL_GOOD_CD, sizeof(ALL_GOOD_CD), 0) < 0) {
printf("inital all good resp failed");
send(socket, (void*)OTHER_BAD_CD, sizeof(OTHER_BAD_CD), 0);
return;
}
printf("sent stuff\n");
int free_spot = -1;
for (int i = 0; i < MAXCLIENTS; i++)
if (!clients[i]) free_spot = i;
printf("filtered through clients and got free spot %d\n", free_spot);
if (free_spot == -1) {
printf("didn't find free spot :(\n");
send(socket, (void*)TOO_MANY_CD, sizeof(TOO_MANY_CD), 0);
pthread_mutex_unlock(&clients_mutex);
return;
}
printf("found free spot %d for client %d", free_spot, socket);
clients[free_spot] = (struct client*) calloc(1, sizeof(struct client));
if (clients[free_spot] == NULL) {
send(socket, (void*)OTHER_BAD_CD, sizeof(OTHER_BAD_CD), 0);
pthread_mutex_unlock(&clients_mutex);
return;
}
curr_cl = clients[free_spot];
if (recv(socket, curr_cl->username, sizeof(curr_cl->username), 0) < 0) {
send(socket, (void*)OTHER_BAD_CD, sizeof(OTHER_BAD_CD), 0);
pthread_mutex_unlock(&clients_mutex);
return;
}
// Subscribe client to #ALL automatically
curr_cl->subs[0] = "#ALL";
if (send(socket, (void*)ALL_GOOD_CD, sizeof(ALL_GOOD_CD), 0) < 0) {
printf("send() for final all good failed\n");
send(socket, (void*)OTHER_BAD_CD, sizeof(OTHER_BAD_CD), 0);
pthread_mutex_unlock(&clients_mutex);
return;
}
printf("\taccepted new client %s and now listening\n", curr_cl->username);
pthread_mutex_unlock(&clients_mutex);
return;
}
void DieWithError(char* errorMessage) {
fprintf(stderr, "Dying with error sadface: %s\n", errorMessage);
exit(1);
}
Here is the Makefile
# the compiler: gcc for C
CC = gcc
# compiler flags
CFLAGS = -g
make: ttweetcl.c ttweetsrv.c
gcc -o ttweetcli ttweetcl.c && gcc -o ttweetsrv ttweetsrv.c -lpthread
.PHONY: clean
clean:
rm -f ./ttweetcli ./ttweetsrv

Solved! One comment (now removed) noticed that I was not ending my printf()'s with a \n and therefore was not flushing the buffer. Now that I have added all \n's then the code executes as it should.

Related

SCTP client and server meets error when reading message sent by the other

I'm implementing a simple SCTP client and server with Linux SCTP socket API. Client and server both use one-to-one socket style. After connecting to server, the client sends a hello message to server and the server responds back with its hello message. Here' the code for server and client:
server.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/sctp.h>
#include "common.h"
int main(int argc, char *argv[])
{
int srvr_sock;
struct sockaddr_in srv_addr;
struct sockaddr_in clnt_addr;
struct sctp_sndrcvinfo sndrcvinfo;
struct sctp_event_subscribe event;
socklen_t addr_sz;
char snd_buf[] = "Hello from server";
char rcv_buf[1024] = {0};
int new_fd;
int flags;
int rd_sz;
int ret;
/* One-to-one style */
/* Create socket */
srvr_sock = socket(PF_INET, SOCK_STREAM, IPPROTO_SCTP);
if (srvr_sock < 0)
{
perror("Open srvr_sock");
exit(EXIT_FAILURE);
}
/* Bind to server address */
memset(&srv_addr, 0, sizeof(srv_addr));
srv_addr.sin_family = AF_INET;
srv_addr.sin_port = htons(SERVER_PORT_NUM);
srv_addr.sin_addr.s_addr = inet_addr(SERVER_IP_ADDR_1);
ret = bind(srvr_sock, (struct sockaddr *) &srv_addr, sizeof(srv_addr));
if (ret < 0)
{
perror("Bind srvr_sock");
exit(EXIT_FAILURE);
}
/* Enable all events */
event.sctp_data_io_event = 1;
event.sctp_association_event = 1;
event.sctp_address_event = 1;
event.sctp_send_failure_event = 1;
event.sctp_peer_error_event = 1;
event.sctp_shutdown_event = 1;
event.sctp_partial_delivery_event = 1;
event.sctp_adaptation_layer_event = 1;
if (setsockopt(srvr_sock, IPPROTO_SCTP, SCTP_EVENTS, &event,
sizeof(event)) != 0)
{
perror("setsockopt failed");
exit(EXIT_FAILURE);
}
/* Listen */
ret = listen(srvr_sock, 5);
if (ret < 0)
{
perror("Listen on srvr_sock");
exit(EXIT_FAILURE);
}
/* Server loop */
while (1)
{
printf("Waiting for new connection...\n");
new_fd = accept(srvr_sock, (struct sockaddr *)&clnt_addr, &addr_sz);
if (new_fd < 0)
{
perror("Failed to accept client connection");
continue;
}
memset(rcv_buf, 0, sizeof(rcv_buf));
rd_sz = sctp_recvmsg(new_fd, (void *)rcv_buf, sizeof(rcv_buf),
(struct sockaddr *) NULL,
0,
&sndrcvinfo,
&flags);
if (rd_sz <= 0)
{
continue;
}
if (flags & MSG_NOTIFICATION)
{
printf("Notification received. rd_sz=%d\n", rd_sz);
}
printf("New client connected\n");
printf("Received %d bytes from client: %s\n", rd_sz, rcv_buf);
/* Send hello to client */
ret = sctp_sendmsg(new_fd, /* sd */
(void *) snd_buf, /* msg */
strlen(snd_buf), /* len */
NULL, /* to */
0, /* to len */
0, /* ppid */
0, /* flags */
STREAM_ID_1, /* stream_no */
0, /* TTL */
0 /* context */);
if (ret < 0)
{
perror("Error when send data to client");
}
else
{
printf("Send %d bytes to client\n", ret);
}
if (close(new_fd) < 0)
{
perror("Close socket failed");
}
}
close(srvr_sock);
return 0;
}
client.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/sctp.h>
#include "common.h"
int main(int argc, char *argv[])
{
int conn_fd;
struct sockaddr_in srvr_addr;
struct sctp_sndrcvinfo sndrcvinfo;
socklen_t addr_sz = sizeof(struct sockaddr_in);
int flags;
char rcv_buf[1024] = {0};
char snd_buf[] = "Hello from client";
int rcv_cnt;
int ret;
/* One-to-one style */
/* Create socket */
conn_fd = socket(PF_INET, SOCK_STREAM, IPPROTO_SCTP);
if (conn_fd < 0)
{
perror("Create socket conn_fd");
exit(EXIT_FAILURE);
}
/* Specify the peer endpoint to which we'll connect */
memset(&srvr_addr, 0, sizeof(srvr_addr));
srvr_addr.sin_family = AF_INET;
srvr_addr.sin_port = htons(SERVER_PORT_NUM);
srvr_addr.sin_addr.s_addr = inet_addr(SERVER_IP_ADDR_1);
/* Connect */
ret = connect(conn_fd, (struct sockaddr *)&srvr_addr, sizeof(srvr_addr));
if (ret < 0)
{
perror("Connect failed");
exit(EXIT_FAILURE);
}
printf("Connected to server\n");
/* Send hello to server */
ret = sctp_sendmsg(conn_fd, (void *)snd_buf, strlen(snd_buf),
(struct sockaddr *) &srvr_addr, sizeof(srvr_addr), 0,
0, STREAM_ID_1, 0, 0);
if (ret < 0)
{
perror("Send to server failed");
close(conn_fd);
exit(EXIT_FAILURE);
}
else
{
printf("Send %d bytes to server\n", ret);
}
/* Read message from server */
rcv_cnt = sctp_recvmsg(conn_fd, (void *)rcv_buf, sizeof(rcv_buf),
(struct sockaddr *) &srvr_addr, &addr_sz,
&sndrcvinfo, &flags);
if (rcv_cnt <= 0)
{
printf("Socket error or EOF\n");
}
else if (flags & MSG_NOTIFICATION)
{
printf("Notification received. rcv_cnt=%d\n", rcv_cnt);
}
else
{
printf("Received %d bytes from server: %s\n", rcv_cnt, rcv_buf);
}
/* close socket */
close(conn_fd);
return 0;
}
common.h
#define SERVER_PORT_NUM 16789
#define SERVER_IP_ADDR_1 "192.168.56.102"
#define STREAM_ID_1 1
Client and server are running on 2 Debian VMs in the same subnet, client's IP is 192.168.56.101, server's IP is 192.168.56.102.
When I start the server and then run the client, most of the time the client fails with following output:
./client
Connected to server
Send to server failed: Cannot assign requested address
However the server shows that it has read data sent from client and has responded with server hello message:
./server
Waiting for new connection...
Notification received. rd_sz=20
New client connected
Received 20 bytes from client: ▒
Send 17 bytes to client
Waiting for new connection...
Also the data received from client is corrupted in this case.
I tried to run the client many times and sometimes it succeeds:
$ ./client
Connected to server
Send 17 bytes to server
Received 17 bytes from server: Hello from server
The server still shows same log messages in this case.
Why would the client fail most of the time while only succeed a few times? The result seems to be unpredictable to me. Also why the data read by server is corrupted in server's output?
Try to bind also client socket.
In client.c between socket create and before connect put:
cli_addr.sin_family = AF_INET;
cli_addr.sin_port = 0;
cli_addr.sin_addr.s_addr = inet_addr(INADDR_ANY); /* or inet_addr("192.168.56.101");
for multiple ip addresses or network cards */
ret = bind(conn_fd, (struct sockaddr *) &cli_addr, sizeof(cli_addr));
if (ret < 0)
{
perror("Bind client_sock");
exit(EXIT_FAILURE);
}

Communication: Sending a message from a client to a server

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

Whois service using UDP

Hell all. I was working on a server c project, using UDP for a whois service.
But I got error: "No whois is service on this host." Here's my code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <pwd.h>
#define BACKLOG 5 /* # of requests we're willing to queue */
#define MAXHOSTNAME 32 /* maximum host name length we tolerate */
main(argc,argv)
int argc; /* standard UNIX argument declarations */
char *argv[];
{
int s,t; /* socket descriptors */
int i; /* general purpose integer */
struct sockaddr_in sa,isa; /* Internet socket address structure */
struct hostent *hp; /* result of host name lookup */
char *myname; /* pointer to name of this program */
struct servent *sp; /* result of service lookup */
char localhost[MAXHOSTNAME+1]; /* local host name as character string */
myname = argv[0];
/*
* Look up the WHOIS service entry
*/
if((sp = getservbyname("whois","udp")) == NULL){
fprintf(stderr, "%s: No whois service on this host\n", myname);
exit(1);
}
/*
* Get our own host information
*/
gethostname(localhost, MAXHOSTNAME);
if((hp = gethostbyname(localhost)) == NULL){
fprintf(stderr, "%s: cannot get local host info?\n", myname);
exit(1);
}
printf("host name is: %s\n",hp->h_name);
printf("my name is: %s\n",myname);
/*
* Put the WHOIS socket number and our address info into the socket structure
*/
u_short portbase = 0;
portbase = 5000;
sa.sin_port = sp->s_port;
sa.sin_port = htons(ntohs((u_short)sp->s_port)+portbase);
bcopy((char *)hp->h_addr, (char *)&sa.sin_addr, hp->h_length);
sa.sin_family = hp->h_addrtype;
/*
* Allocate an open socket for incoming connections
*/
if((s = socket(hp->h_addrtype, SOCK_DGRAM, 0)) < 0){
perror("socket");
exit(1);
}
/*
* Bind the socket to the service port
*/
if(bind(s, (struct sockaddr *)&sa, sizeof sa) < 0){
perror("bind");
exit(1);
}
/*
* Set maximum connections we will fall behind
*/
//listen(s,BACKLOG);
/*
* Go into an infinite loop waiting for new connections
*/
while(1){
i = sizeof isa;
/*
* We hang in accept() while waiting for new customers
*/
/*
if((t = accept(s, (struct sockaddr *)&isa, &i)) < 0){
perror("accept");
exit(1);
}
*/
whois(s); /* perform the actual WHOIS service */
close(s);
}
}
/*
* Get the WHOIS request from remote host and format a reply.
*/
whois(sock)
int sock;
{
struct sockaddr_in clientAddr;
socklen_t len = sizeof(clientAddr);
memset(&clientAddr, 0, sizeof(clientAddr));
struct passwd *p;
char buf[BUFSIZ+1];
int i;
/*
* Get one line request
*/
printf("start to recv data\n");
if((i = recvfrom(sock, buf, BUFSIZ, 0, (struct sockaddr*)&clientAddr, &len)) <= 0)
printf("recv failed\n");
return;
buf[i] = '\0'; /* Null terminate */
printf("After the read, the buf is: %s \n",buf);
/*
* Look up the requested user and format reply
*/
if((p = getpwnam(buf)) == NULL)
strcpy(buf, "User not found\n");
else
sprintf(buf, "%s: %s (from me)\n", p->pw_name, p->pw_gecos);
/*
* Return reply
*/
//write(sock, buf, strlen(buf));
sendto(sock, buf, strlen(buf), 0, (struct sockaddr*)&clientAddr, len);
return;
}
I couldn't figure out where's error. I have a similar code using TCP for whois which runs no problem.
WHOIS is a TCP service. It is not available over UDP.
Additionally, what you are writing is not a WHOIS server at all. WHOIS is a protocol implemented by domain and IP registrars to communicate ownership information (e.g, to look up the owner of a domain name). What you are writing here appears to be a NIS service of some sort - this is not WHOIS, and should not use the same port.

OpenSSL and Network namespace - Closed

I am developing an application using OpenSSL library. I am new to OpenSSL library. My application was working correctly until I tested it within network namespace. My application hangs at SSL_Connect. I am using sockets in the blocking mode. I read somewhere that I should use non-blocking mode instead to solve the issue. So I switched from blocking sockets to non-blocking sockets but my code still gets stuck at SSL_Connect method in the client.
I just have a simple client-server program nothing fancy stuff. I have added SSL methods inside them to make them secure. Everything works perfectly when I run them inside terminal but when I switch to network namespace and run inside virtual network, the client code hangs at SSL_Connect. I am not able to understand what may be causing this problem. Any help will be appreciated!
Here is the code for server.c file:
#include <stdio.h>
#include <stdlib.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <netinet/in.h>
#include <errno.h>
#include <sys/select.h>
#include <sys/types.h>
#include <unistd.h>
#include <string.h>
#include <openssl/ssl.h>
#include <openssl/err.h>
#define SERVER_PORT 12345
#define TRUE 1
#define FALSE 0
main (int argc, char *argv[])
{
int i, len, rc, on = 1;
int listen_sd, max_sd, new_sd;
int desc_ready, end_server = FALSE;
int close_conn;
char buffer[80];
struct sockaddr_in addr;
struct timeval timeout;
fd_set master_set, working_set;
char ch='a';
//ssl initiation
SSL_load_error_strings();
ERR_load_BIO_strings();
ERR_load_SSL_strings();
SSL_library_init();
OpenSSL_add_all_algorithms();
SSL_METHOD *meth = SSLv3_server_method();
SSL_CTX *ctx = SSL_CTX_new(meth);
SSL_CTX_use_certificate_file(ctx, "TrustStore.pem", SSL_FILETYPE_PEM);
SSL_CTX_use_PrivateKey_file(ctx, "privatekey.key", SSL_FILETYPE_PEM);
/*************************************************************/
/* Create an AF_INET stream socket to receive incoming */
/* connections on */
/*************************************************************/
listen_sd = socket(AF_INET, SOCK_STREAM, 0);
if (listen_sd < 0)
{
perror("socket() failed");
exit(-1);
}
/*************************************************************/
/* Allow socket descriptor to be reuseable */
/*************************************************************/
rc = setsockopt(listen_sd, SOL_SOCKET, SO_REUSEADDR,
(char *)&on, sizeof(on));
if (rc < 0)
{
perror("setsockopt() failed");
close(listen_sd);
exit(-1);
}
/*************************************************************/
/* Set socket to be non-blocking. All of the sockets for */
/* the incoming connections will also be non-blocking since */
/* they will inherit that state from the listening socket. */
/*************************************************************/
rc = ioctl(listen_sd, FIONBIO, (char *)&on);
if (rc < 0)
{
perror("ioctl() failed");
close(listen_sd);
exit(-1);
}
/*************************************************************/
/* Bind the socket */
/*************************************************************/
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = htonl(INADDR_ANY);
addr.sin_port = htons(SERVER_PORT);
rc = bind(listen_sd,
(struct sockaddr *)&addr, sizeof(addr));
if (rc < 0)
{
perror("bind() failed");
close(listen_sd);
exit(-1);
}
/*************************************************************/
/* Set the listen back log */
/*************************************************************/
rc = listen(listen_sd, 32);
if (rc < 0)
{
perror("listen() failed");
close(listen_sd);
exit(-1);
}
/*************************************************************/
/* Initialize the master fd_set */
/*************************************************************/
FD_ZERO(&master_set);
max_sd = listen_sd;
FD_SET(listen_sd, &master_set);
/*************************************************************/
/* Initialize the timeval struct to 3 minutes. If no */
/* activity after 3 minutes this program will end. */
/*************************************************************/
timeout.tv_sec = 3 * 60;
timeout.tv_usec = 0;
/*************************************************************/
/* Loop waiting for incoming connects or for incoming data */
/* on any of the connected sockets. */
/*************************************************************/
do
{
/**********************************************************/
/* Copy the master fd_set over to the working fd_set. */
/**********************************************************/
memcpy(&working_set, &master_set, sizeof(master_set));
/**********************************************************/
/* Call select() and wait 5 minutes for it to complete. */
/**********************************************************/
printf("Waiting on select()...\n");
rc = select(max_sd + 1, &working_set, NULL, NULL, &timeout);
/**********************************************************/
/* Check to see if the select call failed. */
/**********************************************************/
if (rc < 0)
{
perror(" select() failed");
break;
}
/**********************************************************/
/* Check to see if the 5 minute time out expired. */
/**********************************************************/
if (rc == 0)
{
printf(" select() timed out. End program.\n");
break;
}
/**********************************************************/
/* One or more descriptors are readable. Need to */
/* determine which ones they are. */
/**********************************************************/
desc_ready = rc;
for (i=0; i <= max_sd && desc_ready > 0; ++i)
{
/*******************************************************/
/* Check to see if this descriptor is ready */
/*******************************************************/
if (FD_ISSET(i, &working_set))
{
/****************************************************/
/* A descriptor was found that was readable - one */
/* less has to be looked for. This is being done */
/* so that we can stop looking at the working set */
/* once we have found all of the descriptors that */
/* were ready. */
/****************************************************/
desc_ready -= 1;
/****************************************************/
/* Check to see if this is the listening socket */
/****************************************************/
if (i == listen_sd)
{
printf(" Listening socket is readable\n");
/*************************************************/
/* Accept all incoming connections that are */
/* queued up on the listening socket before we */
/* loop back and call select again. */
/*************************************************/
do
{
/**********************************************/
/* Accept each incoming connection. If */
/* accept fails with EWOULDBLOCK, then we */
/* have accepted all of them. Any other */
/* failure on accept will cause us to end the */
/* server. */
/**********************************************/
new_sd = accept(listen_sd, NULL, NULL);
if (new_sd < 0)
{
if (errno != EWOULDBLOCK)
{
perror(" accept() failed");
end_server = TRUE;
}
break;
}
/**********************************************/
/* Add the new incoming connection to the */
/* master read set */
/**********************************************/
printf(" New incoming connection - %d\n", new_sd);
FD_SET(new_sd, &master_set);
if (new_sd > max_sd)
max_sd = new_sd;
/**********************************************/
/* Loop back up and accept another incoming */
/* connection */
/**********************************************/
} while (new_sd != -1);
}
/****************************************************/
/* This is not the listening socket, therefore an */
/* existing connection must be readable */
/****************************************************/
else
{
printf(" Descriptor %d is readable\n", i);
close_conn = FALSE;
SSL* ssl;
ssl = SSL_new(ctx);
SSL_set_fd(ssl, i);
//handshake
SSL_accept(ssl);
printf("\nHandshake Done\n");
int result = SSL_read(ssl, &ch, sizeof(ch));
if(result<0)
{
printf("\nreading Error");
}
++ch;
result = SSL_write(ssl, &ch, sizeof(ch));
if(result<0)
{
printf("\nwriting Error");
}
/*************************************************/
/* If the close_conn flag was turned on, we need */
/* to clean up this active connection. This */
/* clean up process includes removing the */
/* descriptor from the master set and */
/* determining the new maximum descriptor value */
/* based on the bits that are still turned on in */
/* the master set. */
/*************************************************/
if (close_conn)
{
close(i);
FD_CLR(i, &master_set);
if (i == max_sd)
{
while (FD_ISSET(max_sd, &master_set) == FALSE)
max_sd -= 1;
}
}
} /* End of existing connection is readable */
} /* End of if (FD_ISSET(i, &working_set)) */
} /* End of loop through selectable descriptors */
} while (end_server == FALSE);
/*************************************************************/
/* Cleanup all of the sockets that are open */
/*************************************************************/
for (i=0; i <= max_sd; ++i)
{
if (FD_ISSET(i, &master_set))
close(i);
}
}
Here is the code for client.c file:
/**************************************************************************/
/* Generic client example is used with connection-oriented server designs */
/**************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <string.h>
#include <openssl/ssl.h>
#include <openssl/err.h>
#define SERVER_PORT 12345
main (int argc, char *argv[])
{
int len, rc;
int sockfd;
char send_buf[80];
char recv_buf[80];
struct sockaddr_in addr;
char ch = 'A';
int result;
//ssl initiation
SSL_load_error_strings();
ERR_load_BIO_strings();
ERR_load_SSL_strings();
SSL_library_init();
OpenSSL_add_all_algorithms();
SSL_METHOD *meth;
meth = SSLv3_client_method();
SSL_CTX *ctx;
SSL* ssl;
ctx = SSL_CTX_new(meth);
result = SSL_CTX_load_verify_locations(ctx, "TrustStore1.pem", 0);
printf("\nCA load result = %d\n", result);
printf("\nSSL initialized");
/*************************************************/
/* Create an AF_INET stream socket */
/*************************************************/
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0)
{
perror("socket");
exit(-1);
}
/*************************************************/
/* Initialize the socket address structure */
/*************************************************/
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = inet_addr("10.0.0.1");
addr.sin_port = htons(SERVER_PORT);
/*************************************************/
/* Connect to the server */
/*************************************************/
rc = connect(sockfd,
(struct sockaddr *)&addr,
sizeof(struct sockaddr_in));
if (rc < 0)
{
perror("connect");
close(sockfd);
exit(-1);
}
printf("Connect completed.\n");
//ssl-ing the connection
ssl = SSL_new(ctx);
BIO *sbio;
sbio = BIO_new(BIO_s_socket());
BIO_set_fd(sbio, sockfd, BIO_CLOSE);
SSL_set_bio(ssl, sbio, sbio);
//SSL_CTX_set_verify_depth(ctx, 1);
//SSL_set_fd(ssl, sockfd);
printf("Before SSL_connect: %d\n", result);
result = SSL_connect(ssl);
printf("SSL_connect: %d\n", result);
if(SSL_get_peer_certificate(ssl)!=NULL)
{
//check cert
//check_cert(ssl);
//getting the CA certificate
//_ssl = SSL_new(ctx);
SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, NULL);
int result_long = SSL_get_verify_result(ssl);
printf("\nCertificate Check Result: %d", result_long);
if (SSL_get_verify_result(ssl) != X509_V_OK)
{
printf("\nCertiticate Verification Failed\n");
return 0;
//exit(1);
}
else
{
printf("\nCertiticate Verification Succeeded");
}
}
SSL_write(ssl, &ch, 1);
SSL_read(ssl, &ch, 1);
printf("char from server = %c\n", ch);
SSL_shutdown(ssl);
/*************************************************/
/* Close down the socket */
/*************************************************/
close(sockfd);
}

recv does not save the whole message in the buffer

I use send and recv to pass messages between a client and a server. On the server side when i receive a message on buffer fname the message saved is not the whole message that has been sent from client
SERVER
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <sys/types.h> /*For Sockets*/
#include <sys/socket.h> /*For Sockets*/
#include <netdb.h> /*For gethostbyaddr()*/
#include <netinet/in.h> /*For internet sockets*/
#include <dirent.h>
/*Function for creating the lof file of Server*/
void log_event (char *message,char *filename)
{
FILE *file;
char *log_this;
time_t system_time; //Get the system time
time(&system_time);
log_this=strcat(ctime(&system_time),message); //Create the message to log
/*Check for filename and log as appropiate*/
if (filename!=NULL)
{
file = fopen(filename,"a+");
fprintf(file,"%s",log_this); /*writes the message*/
fclose(file); /*done!*/
}
else
{
file = fopen("ftp_tracelog.txt","a+");
fprintf(file,"%s",log_this); /*writes the message*/
fclose(file); /*done!*/
}
}
int main (int argc,char *argv[])
{
/*DECLERATIONS*/
char *filename;
char message [1024];
char *temp;
char temp_2[1024];
char fname[128];
char request[1024];
char op[1000];
char command[5];
FILE *fp;
DIR *dp;
char list[1024];
int port,sock,newsock,serverlen,clientlen,fname_len,recvMsgSize,i;
char buf[256];
struct sockaddr_in server,client;
struct sockaddr *serverptr, *clientptr;
struct hostent *rem;
struct dirent *ep;
/*END OF DECLERATIONS*/
/*Check for required arguments and get them as appropiate*/
if (argc < 2) {
/* Check if server's port number is given */
printf("Please give the port number!!!\n");
exit(1);
}
/*if server's port number is given and filename for log is given*/
if(argc>2){
filename=argv[1];
port=atoi(argv[2]);
}
/*If only port is given*/
if (argc==2){
port=atoi(argv[1]);
filename=NULL;
}
temp="--Server is Starting!!--";
sprintf(message,"%s\n",temp);
log_event(message,filename);
/* Create socket */
if ((sock = socket(PF_INET, SOCK_STREAM, 0)) < 0)
{perror("socket"); exit(1); }
server.sin_family = PF_INET; /* Internet domain */
server.sin_addr.s_addr = htonl(INADDR_ANY); /* My Internet address */
server.sin_port = htons(port); /* The given port */
serverptr = (struct sockaddr *) &server;
serverlen = sizeof (server);
/* Bind socket to address */
if (bind(sock, serverptr, serverlen) < 0) {
perror("bind"); exit(1); }
/* Listen for connections */
if (listen(sock, 40) < 0) { /* 5 max. requests in queue */
perror("listen"); exit(1); }
temp="---Listening for connections to port";
sprintf(temp_2,"%d----",port);
sprintf(message,"%s:%s\n",temp,temp_2);
log_event(message,filename);
/*Accepting Connecttion*/
while(1) {
clientptr = (struct sockaddr *) &client;
clientlen = sizeof(client);
/* Accept connection */
if ((newsock = accept(sock, clientptr, &clientlen)) < 0) {
perror("accept"); exit(1); }
/* Find client's address */
if ((rem = gethostbyaddr((char *) &client.sin_addr.s_addr,
sizeof (client.sin_addr.s_addr), client.sin_family)) == NULL) {
perror("gethostbyaddr"); exit(1);
}
temp="----Accepted connection from ";
sprintf(temp_2,"%s----", rem -> h_name);
sprintf(message,"%s:%s\n",temp,temp_2);
log_event(message,filename);
/* Create child for serving the client */
switch (fork()) {
case -1:
perror("fork"); exit(1);
case 0: /* Child process */
do{
/* Receive message from client */
if ((recvMsgSize = recv(newsock,request,sizeof(request),0))< 0)
perror("recv() failed");
//printf("%s\n",request);
strncpy(command,request,4);
printf("%s\n",command);
/*IF YOU ARE GOING TO EXECUTE AN LS COMMAND*/
if (strcmp(command,"ls")==0)
{
dp = opendir ("./");
if (dp != NULL)
{ /*LOG LS REQUEST*/
temp="--Client ";
sprintf(temp_2,"%s requested ls -------",rem -> h_name);
sprintf(message,"%s:%s\n",temp,temp_2);
log_event(message,filename);
/*SEND ALL DIRECTORY LISTING*/
while (ep = readdir (dp))
{
strcpy(list,ep->d_name);
//printf("sending:%s\n",list);
if (send(newsock,list,sizeof(list), 0)!= sizeof(list))
perror("send() sent a different number of bytes than expected");
}
//IF DIRECORY IS FINISHED SEND A LAST MESSAGE FOR ENDING
(void) closedir (dp);
if (send(newsock,"end",sizeof("end"), 0)!= sizeof("end"))
perror("send() sent a different number of bytes than expected");
}
else
perror ("Couldn't open the directory");
}
/*IF THE COMMAND IS PUT*/
if (strcmp(command,"put")==0)
{
printf("execute put!!\n");
bzero(fname, sizeof fname); /* Initialize buffer */
if ((recvMsgSize = recv(newsock,fname,128, MSG_WAITALL)) < 0)
perror("recv() failed");
printf("%s!!!!\n",fname);
}
}while (strcmp(request,"end")!=0); //run until client sents end request
/*LOG EXIT OF CLIENT*/
temp="--Client";
sprintf(temp_2,"%s is disconnected---",rem -> h_name);
sprintf(message,"%s:%s\n",temp,temp_2);
log_event(message,filename);
close(newsock); /* Close socket */
exit(0);
} /* end of switch */
} /* end of while(1) */
}
CLIENT
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <netdb.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/types.h>
int main (int argc,char *argv[])
{
int port, sock, serverlen,recvMsgSize;
int fname_len,msg_len,request_len;
char buf[256];
char fname[128];
char request[1204];
char list[1024];
char msg[512];
char op[1000];
char temp[5];
char *temp3;
FILE *fp;
struct sockaddr_in server;
struct sockaddr *serverptr;
struct hostent *rem;
temp3="put";
/* Are server's host name and port number given? */
if (argc < 3) {
printf("Please give host name and port number\n"); exit(1);
}
/* Create socket */
if ((sock = socket(PF_INET, SOCK_STREAM, 0)) < 0) {
perror("socket");
exit(1);
}
/* Find server address */
if ((rem = gethostbyname(argv[1])) == NULL) {
herror("gethostbyname"); exit(1);
}
/* Convert port number to integer */
port = atoi(argv[2]);
/* Internet domain */
server.sin_family = PF_INET;
bcopy((char *) rem -> h_addr, (char *) &server.sin_addr,
rem -> h_length);
/*Server's Internet address and port*/
server.sin_port = htons(port);
serverptr = (struct sockaddr *) &server;
serverlen = sizeof(server);
if (connect(sock, serverptr, serverlen) < 0) { /* Request connection */
perror("connect");
exit(1); }
printf("Requested connection to host %s port %d\n", argv[1], port);
do{
printf("Please enter request\n:");
scanf("%s",request);
request_len=sizeof(request);
/* Send the string to the server */
if (send(sock,request,request_len, 0)!= request_len)
perror("send() sent a different number of bytes than expected");
strncpy(temp,request,4);
printf("%s\n",temp);
if(strcmp(temp,"ls")==0)
{
sprintf(list,"");
/*Recieve from server*/
while(strcmp(list,"end")!=0){
if ((recvMsgSize = recv(sock,list,sizeof(list),0))< 0)
perror("recv() failed");
if(strcmp(list,"end")!=0){
printf("%s\n",list);
}
}
}
/*Command for put*/
if(strcmp(request,temp)==0)
{
printf("Please enter filename:\n");
scanf("%s",fname);
if (send(sock,fname,128, MSG_DONTWAIT)!= 128)
perror("send() sent a different number of bytes than expected");
}
}while (strcmp(request,"end")!=0);
close(sock); /* Close socket */
exit(0);
}
When you call recv, you need to check the number of bytes received. If it is less than you asked for, you need to call recv again, and add to the end of the previously received buffer. What is probably happening, is that only part of the message has arrived when you first call recv.
char buf[N];
char* p = buf;
ssize_t bytesRemaining = N;
while (bytesRemaining) {
ssize_t recvd;
recvd = recv(sock, p, bytesRemaining, 0);
bytesRemaining -= recvd; // keep track of bytes left
p += recvd; // advance buffer pointer
}
One can never rely on recv() function receiving all the data in one instance of the call. You might have to call it repeatedly in a loop to fetch all the data(equal to the length of the data.

Resources