I am making an assignment in which a server fork's multiple children, one for each sensor connected to the server (and each child then has a tcp connection to that sensor node).
Now as it's my first time working with fork's, I'm not entirely sure it's working correctly.
The tcpsocket.h is a file provided, giving some basic tcp-functionality. This is working, since the data is sent and received succesfully.
Here's a short explanation of the code: The main process listens passively to incoming tcp connections. The tcp_wait_for_connection() waits in blocking mode for a connection to be established. Once this is done, it should give the connection to a new child. The Child should of course then close the passive listening on the port, and the main process should not listen to the connection with the sensor.
Now it all works fine, but I'm not sure whether children are correctly killed. A sensorNode for example just quits (cntrl + c), thus the connection stops, but I'm not sure whether the child then dies or keeps looping for eternity. I've also included tcpsocket.c since this might give more clarity.
server.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>
#include "tcpsocket.h"
#define BUFSIZE 1024
#define PORT 1234
struct package{
unsigned sensorId:12;
unsigned sequence:4;
unsigned flag:2;
unsigned sign:1;
unsigned value:12;
unsigned parity:1;
};
typedef struct package packs;
union sensor{
packs pack;
unsigned sensorValue;
};
typedef union sensor Sensor;
char buffer[BUFSIZE];
int main( void )
{
Socket server, client;
int bytes;
server = tcp_passive_open( PORT );
while( 1 ) {
client = tcp_wait_for_connection( server );
#ifdef DEBUG
printf("Incoming client connection\n");
#endif
pid_t pid;
pid = fork();
if(pid == -1){
printf("Something went wrong creating a child.\n");
}else if(pid == 0){
tcp_close( &server );
#ifdef DEBUG
pid_t parentPid;
parentPid = getppid();
printf("New child created with parent id %d, own pid: %d\n",parentPid, pid);
#endif
Sensor * mySensor = malloc(sizeof(packs));
while(1){
memset(buffer, 0, BUFSIZE);
bytes = tcp_receive( client, (void *)buffer, BUFSIZE );
if(bytes > 0){
mySensor->sensorValue = atoi(buffer);
#ifdef DEBUG
printf("Received message of %d bytes. ID: %i, Sequence: %i, flag: %i, sign: %i, value: %i\n",
bytes, mySensor->pack.sensorId, mySensor->pack.sequence, mySensor->pack.flag, mySensor->pack.sign, mySensor->pack.value);
#endif
}
}
tcp_close( &client );
exit(0);
}
tcp_close( &client );
}
tcp_close( &server );
return 0;
}
tcpsocket.c
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "tcpsocket.h"
#define CHAR_IP_ADDR_LENGTH 16 // 4 numbers of 3 digits, 3 dots and \0
#define ERROR_SD -1
#define ERROR_PORT 0
#define MIN_PORT 1
#define MAX_PORT 65536
#define PROTOCOLFAMILY AF_INET // internet protocol suite
#define TYPE SOCK_STREAM // streaming protool type
#define PROTOCOL IPPROTO_TCP // TCP protocol
typedef struct {
int sd;
char *ip_addr;
int port;
} MySocket; // My definition of a socket: a socket descriptor,
// the IP address and port number of the PC hosting this socket
// private functions used for error checking
static void die(char* message);
static void check_socket_ptr(char *pre_msg, Socket s);
static void check_sd(char *pre_msg, int sd);
static void check_ip_addr(char *pre_msg, char *ip_addr);
static void check_port(char *pre_msg, int port);
// private error message string
static char error_msg[256];
/*-------------------------------------------------------------------------------------*/
Socket tcp_passive_open(int port)
/*-------------------------------------------------------------------------------------*/
{
// parameter check
check_port("tcp_open_server() failed", port);
MySocket *s = (MySocket *)malloc( sizeof(MySocket) );
if ( s == NULL )
die("tcp_open__socket() failed: mem alloc error");
struct sockaddr_in addr;
s->sd = socket(PROTOCOLFAMILY, TYPE, PROTOCOL);
check_sd("tcp_open_server failed(): socket creation error", s->sd);
/* Construct the server address structure */
memset(&addr, 0, sizeof(struct sockaddr_in));
addr.sin_family = PROTOCOLFAMILY;
addr.sin_addr.s_addr = htonl(INADDR_ANY);
addr.sin_port = htons(port);
if ( bind(s->sd, (struct sockaddr *)&addr, sizeof(addr)) != 0 ) {
die("tcp_open_server failed(): bind() failed"); //will fail if e.g; port is in use
}
if( listen(s->sd, MAX_PENDING) != 0 )
die("tcp_open_server failed(): listen() failed");
s->port = port;
s->ip_addr = NULL; //INADDR_ANY ...
return (Socket)s;
}
/*-------------------------------------------------------------------------------------*/
Socket tcp_active_open( int remote_port, char *remote_ip )
/*-------------------------------------------------------------------------------------*/
{
// parameter check
check_port("tcp_open_client() failed", remote_port);
check_ip_addr("tcp_open_client() failed", remote_ip);
MySocket *client = (MySocket *)malloc( sizeof(MySocket) );
if ( client == NULL )
die("tcp_open_client() failed: mem alloc error");
struct sockaddr_in addr;
int length;
char *p;
client->sd = socket(PROTOCOLFAMILY, TYPE, PROTOCOL);
check_sd("tcp_open_client() failed: socket creation error", client->sd);
/* Construct the server address structure */
memset(&addr, 0, sizeof(struct sockaddr_in));
addr.sin_family = PROTOCOLFAMILY;
if ( inet_aton(remote_ip, (struct in_addr *) &addr.sin_addr.s_addr) == 0 )
die("tcp_open_client failed(): invalid ip address");
addr.sin_port = htons(remote_port);
if ( connect(client->sd, (struct sockaddr *) &addr, sizeof(addr) ) < 0 )
die("tcp_open_client failed(): connect () failed");
memset(&addr, 0, sizeof(struct sockaddr_in));
length = sizeof(addr);
if ( getsockname(client->sd, (struct sockaddr *)&addr, (socklen_t *)&length) != 0 )
die("tcp_open_client failed(): getsockname() failed");
p = inet_ntoa(addr.sin_addr); //returns addr to statically allocated buffer
client->ip_addr = (char *)malloc( sizeof(char)*CHAR_IP_ADDR_LENGTH);
if ( client->ip_addr == NULL )
die("tcp_open_client failed(): mem alloc error");
client->ip_addr = strcpy( client->ip_addr, p );
client->port = ntohs(addr.sin_port);
return (Socket)client;
}
/*-------------------------------------------------------------------------------------*/
Socket tcp_wait_for_connection( Socket socket )
/*-------------------------------------------------------------------------------------*/
{
// parameter check
check_socket_ptr("tcp_wait_for_connection() failed", socket);
MySocket *serv = (MySocket *)socket;
MySocket *clie = (MySocket *)malloc( sizeof(MySocket) );
if ( clie == NULL )
die("tcp_wait_for_connection() failed: mem alloc error");
struct sockaddr_in addr;
unsigned int length = sizeof(struct sockaddr_in);
char *p;
check_sd("tcp_wait_for_connection() failed", serv->sd);
clie->sd = accept(serv->sd, (struct sockaddr*) &addr, &length);
check_sd("tcp_wait_for_connection() failed: accept() error", clie->sd);
p = inet_ntoa(addr.sin_addr); //returns addr to statically allocated buffer
clie->ip_addr = (char *)malloc( sizeof(char)*CHAR_IP_ADDR_LENGTH);
if ( clie->ip_addr == NULL )
die("tcp_wait_for_connection failed(): mem alloc error");
clie->ip_addr = strcpy( clie->ip_addr, p );
clie->port = ntohs(addr.sin_port);
return (Socket)clie;
}
/*-------------------------------------------------------------------------------------*/
void tcp_close( Socket *socket )
/*-------------------------------------------------------------------------------------*/
{
// parameter check
check_socket_ptr("tcp_close() failed", socket);
check_socket_ptr("tcp_close() failed", *socket);
MySocket *s = (MySocket *)*socket;
check_sd("tcp_close() failed", s->sd);
close( s->sd );
free(s);
*socket = NULL;
}
/*-------------------------------------------------------------------------------------*/
void tcp_send(Socket socket, void *buffer, int bufsize )
/*-------------------------------------------------------------------------------------*/
{
// parameter check
check_socket_ptr("tcp_send() failed", socket);
if ( buffer == NULL )
die("tcp_send failed(): buffer param is NULL");
MySocket *s = (MySocket *)socket;
int result;
int sen = 0;
int to_sen = bufsize;
check_sd("tcp_send() failed", s->sd);
do {
result = send(s->sd, (const void*) (buffer+sen), to_sen, 0);
if (result < 0)
die("tcp_send() failed: not able to send");
sen += result;
to_sen -= result;
} while ( to_sen > 0 );
}
/*-------------------------------------------------------------------------------------*/
int tcp_receive (Socket socket, void* buffer, int bufsize)
/*-------------------------------------------------------------------------------------*/
{
// parameter check
check_socket_ptr("tcp_receive() failed", socket);
if ( buffer == NULL )
die("tcp_receive() failed: buffer param is NULL");
if ( bufsize == 0 )
die("tcp_receive() failed: bufsize is zero");
MySocket *s = (MySocket *)socket;
check_sd("tcp_receive() failed", s->sd);
int rec = recv(s->sd, buffer, bufsize, 0);
return rec;
}
/*-------------------------------------------------------------------------------------*/
char * get_ip_addr( Socket socket )
/*-------------------------------------------------------------------------------------*/
{
// parameter check
check_socket_ptr("get_ip_addr() failed", socket);
MySocket *s = (MySocket *)socket;
check_ip_addr("get_ip_addr() failed", s->ip_addr);
return s->ip_addr;
}
/*-------------------------------------------------------------------------------------*/
int get_port( Socket socket )
/*-------------------------------------------------------------------------------------*/
{
// parameter check
check_socket_ptr("get_port() failed", socket);
MySocket *s = (MySocket *)socket;
check_port("get_port() failed", s->port);
return s->port;
}
/*-------------------------------------------------------------------------------------*/
int get_socket_descriptor( Socket socket )
/*-------------------------------------------------------------------------------------*/
{
// parameter check
check_socket_ptr("get_socket_descriptor() failed", socket);
MySocket *s = (MySocket *)socket;
check_sd("get_socket_descriptor() failed", s->sd);
return s->sd;
}
/*-------------------------------------------------------------------------------------*/
static void die(char* message)
/*-------------------------------------------------------------------------------------*/
{
perror(message);
exit(-1);
}
/*-------------------------------------------------------------------------------------*/
static void check_socket_ptr(char *pre_msg, Socket socket)
/*-------------------------------------------------------------------------------------*/
{
if ( socket == NULL )
{
sprintf(error_msg, "%s: socket ptr is NULL", pre_msg);
die(error_msg);
}
}
/*-------------------------------------------------------------------------------------*/
static void check_sd(char *pre_msg, int sd)
/*-------------------------------------------------------------------------------------*/
{
if ( sd <= ERROR_SD )
{
sprintf(error_msg, "%s: invalid socket descriptor", pre_msg);
die(error_msg);
}
}
/*-------------------------------------------------------------------------------------*/
static void check_ip_addr(char *pre_msg, char *ip_addr)
/*-------------------------------------------------------------------------------------*/
{
if ( ip_addr == NULL )
{
sprintf(error_msg, "%s: invalid socket ip address", pre_msg);
die(error_msg);
}
}
/*-------------------------------------------------------------------------------------*/
static void check_port(char *pre_msg, int port)
/*-------------------------------------------------------------------------------------*/
{
if ( (port < MIN_PORT) || (port > MAX_PORT) )
{
sprintf(error_msg, "%s: invalid socket port", pre_msg);
die(error_msg);
}
}
I'm not sure whether the child then dies or keeps looping for eternity.
In the code you show there are no tests for recv() returning 0 which would indicate that the connection had been closed by the other side.
You might like to modify the code like this
if(bytes > 0){
mySensor->sensorValue = atoi(buffer);
#ifdef DEBUG
printf("Received message of %d bytes. ID: %i, Sequence: %i, flag: %i, sign: %i, value: %i\n",
bytes, mySensor->pack.sensorId, mySensor->pack.sequence, mySensor->pack.flag, mySensor->pack.sign, mySensor->pack.value);
#endif
}
else if (bytes == 0)
{
printf("Connection closed by other side. Exiting ...\n");
break;
}
else /* bytes < 0 */
{
printf("Error receiving. Exiting ...\n");
break;
}
to end the child. There is no need to "kill" any process in term of sending it a SIGKILL signal, btw.
Also the tcp_receive() function misses to test how much data had been received for each call to recv() and then if necessary to loop around recv() until all data requested had been received. (See tcp_send() to see how it is done for send().)
Related
My lecturer gave us his implemented Daytime Protocol in C using TCP and we have to extend it to UDP. It should only accept UDP or TCP using cmd flags -u / -t. I have done everything so far, but the sendto() function returns
"Server started, listening on 0.0.0.0:13 ...
Received message from 127.0.0.1:35585:
Successful incoming connection from 127.0.0.1:35585.
Error in function sending_datetime() line 319: ERROR IN SENDTO(): Socket operation on non-socket
"
I have tried everything but still cant fix it, please help me and thank you :) (iam a beginner)
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <getopt.h>
#include <assert.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netdb.h>
#include <netinet/in.h>
#include <time.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <arpa/inet.h>
#define TCP 1
#define UDP 2
#define PROTO TCP
#define PORT 13
#define BACKLOG 256
#define MSGLENGTH 27
#define XSTR(s) STR(s)
#define STR(s) #s
#define ERROR(str) (fprintf(stderr, "Error in function %s() line %d: ", __FUNCTION__, __LINE__),\
perror(str), kill(0, SIGTERM), exit(EXIT_FAILURE))
#define LOG(...) (printf(__VA_ARGS__), fflush(stdout))
volatile sig_atomic_t active = 1;
/*
* struct srvcfg is used to manage all necessary settings for a daytime service
*/
struct srvcfg {
int proto;
unsigned short port;
struct in_addr server_ip;
struct sockaddr_in server_addr;
int sockfd;
};
/*
* Declaration of functions
*/
void exiting(int sig);
void set_signal_handler(void);
void print_usage(void);
void parse_arguments(int argc, char *argv[], struct srvcfg *cfg);
void start_server(struct srvcfg *cfg);
int create_socket(int type, struct sockaddr_in *addr);
int sending_datetime(int fd, int port);
void destroy_server(struct srvcfg *cfg);
int main(int argc, char *argv[]) {
struct srvcfg *cfg;
struct sockaddr_in client;
int client_len = sizeof(struct sockaddr_in);
int fd;
if ((cfg = malloc(sizeof(struct srvcfg))) == NULL)
ERROR("Error allocating memory");
set_signal_handler();
parse_arguments(argc, argv, cfg);
start_server(cfg);
while (active) {
// Sockets are set to non-blocking, therefor errno needs to be checked
// for EWOULDBLOCK and/or EAGAIN
if (cfg->proto == TCP)
{
if (((fd = accept(cfg->sockfd, (struct sockaddr *)&client, &client_len)) == -1)
&& (errno != EWOULDBLOCK) && (errno != EAGAIN))
ERROR("Error incoming connection");
}
else if (cfg->proto == UDP)
{
char buffer[MSGLENGTH];
if ((fd = recvfrom(cfg->sockfd, buffer, sizeof(buffer), 0, (struct sockaddr *)&client, &client_len)) == -1)
{
if (errno != EWOULDBLOCK && errno != EAGAIN)
ERROR("Error receiving message");
}
else
{
buffer[fd] = '\0';
printf("Received message from %s:%d: %s\n",
inet_ntoa(client.sin_addr), ntohs(client.sin_port), buffer);
}
}
// Only if we get a socket descriptor from the accept() call,
// we continue sending the daytime message
if (fd != -1) {
LOG("Successful incoming connection from %s:%d.\n", \
inet_ntoa(client.sin_addr),ntohs(client.sin_port));
if (cfg->proto == TCP)
{
if (sending_datetime(fd, TCP) == -1)
ERROR("Error sending datetime");
}
else if (cfg->proto == UDP)
{
if (sending_datetime(fd, UDP) == -1)
ERROR("Error sending datetime via UDP");
}
LOG("Successfully sent datetime to %s:%d.\n", \
inet_ntoa(client.sin_addr),ntohs(client.sin_port));
if (close(fd) == -1)
ERROR("Error on closing socket");
LOG("Successfully closing connection from %s:%d.\n", \
inet_ntoa(client.sin_addr),ntohs(client.sin_port));
}
}
destroy_server(cfg);
free(cfg);
exit(EXIT_SUCCESS);
}
* Starting the daytime services by using create_socket() until the socket is in
* listen state.
*/
void start_server(struct srvcfg *cfg)
{
assert(cfg != NULL);
bzero(&cfg->server_addr, sizeof(cfg->server_addr));
cfg->server_addr.sin_family = AF_INET;
cfg->server_addr.sin_port = htons(cfg->port);
cfg->server_addr.sin_addr.s_addr = cfg->server_ip.s_addr;
if (cfg->proto == TCP) {
cfg->sockfd = create_socket(SOCK_STREAM, &cfg->server_addr);
// We set the socket to non-blocking, which means an accept() call won't block
// until a client connection request is received
fcntl(cfg->sockfd, F_SETFL, fcntl(cfg->sockfd, F_GETFL, 0) | O_NONBLOCK);
}
else if (cfg->proto == UDP)
{
cfg->sockfd = create_socket(SOCK_DGRAM, &cfg->server_addr); // UDP Erweiterung
}
LOG("Server started, listening on %s:%d ...\n", inet_ntoa(cfg->server_ip), cfg->port);
}
/*
* Creating a socket in listen state for the daytime service.
*/
int create_socket(int type, struct sockaddr_in *addr)
{
assert(type == SOCK_STREAM || type == SOCK_DGRAM);
assert(addr != NULL);
int sockfd;
int reuseaddr = 1;
if ((sockfd = socket(PF_INET, type, 0)) == -1)
ERROR("Error creating socket");
if ((setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR,
&reuseaddr, sizeof(reuseaddr))) == -1)
ERROR("Error setting socket options");
if ((bind(sockfd, (struct sockaddr *)addr, sizeof(*addr))) == -1)
ERROR("Error binding socket");
if (type == SOCK_STREAM) {
if ((listen(sockfd, BACKLOG)) == -1)
ERROR("Error setting stream socket into listening mode");
}
return sockfd;
}
/*
* Sending a daytime message to the client.
*/
int sending_datetime(int fd, int port)
{
time_t curr_time;
char buffer[MSGLENGTH];
struct sockaddr_in client;
int client_len = sizeof(client);
/*
* A daytime message from this server is 26 bytes long, including a closing \r\n.
* Example: Thu Nov 26 11:29:54 2020\r\n
*/
curr_time = time(NULL);
snprintf(buffer, sizeof(buffer), "%.24s\r\n", ctime(&curr_time));
if (port == TCP)
{
return write(fd, buffer, strlen(buffer));
}
else if (port == UDP)
{
int n;
n = sendto(fd, buffer, strlen(buffer), 0, (struct sockaddr *)&client, client_len);
if (n < 0)
{
ERROR("ERROR IN SENDTO()"); // <---- HERE !!!!***
}
else
return n;
}
//sendto(fd, buffer, strlen(buffer), 0, (struct sockaddr *)&client, sizeof(client));
}
void destroy_server(struct srvcfg *cfg)
{
assert(cfg != NULL);
if ((close(cfg->sockfd)) == -1)
ERROR("Error closing socket");
}
else if (cfg->proto == UDP)
{
char buffer[MSGLENGTH];
if ((fd = recvfrom(cfg->sockfd, buffer, sizeof(buffer), 0, (struct sockaddr *)&client, &client_len)) == -1)
{
if (errno != EWOULDBLOCK && errno != EAGAIN)
From the man page:
Upon successful completion, recvfrom() shall return the length of the
message in bytes. If no messages are available to be received and the
peer has performed an orderly shutdown, recvfrom() shall return 0.
Otherwise, the function shall return -1 and set errno to indicate the
error.
recvfrom() doesn't return a file descriptor. It returns the length of the message in bytes.
A subsequent sendto() operation then tries to write to the return value of recvfrom(), which causes it to fail with EBADF:
The socket argument is not a valid file descriptor.
Fix:
You need to specify the socket descriptor the server is bound to instead of the return value of recvfrom().
The sendto() function shall send a message through a connection-mode
or connectionless-mode socket. If the socket is connectionless-mode,
the message shall be sent to the address specified by dest_addr.
Pass in the struct srvcfg to sending_daytime(), and replace fd with cfg->sock.
int sending_datetime(struct srvcfg *cfg, int fd, int port)
{
time_t curr_time;
char buffer[MSGLENGTH];
struct sockaddr_in client;
int client_len = sizeof(client);
/*
* A daytime message from this server is 26 bytes long, including a closing \r\n.
* Example: Thu Nov 26 11:29:54 2020\r\n
*/
curr_time = time(NULL);
snprintf(buffer, sizeof(buffer), "%.24s\r\n", ctime(&curr_time));
if (port == TCP)
{
return write(fd, buffer, strlen(buffer));
}
else if (port == UDP)
{
int n;
n = sendto(cfg->sockfd, buffer, strlen(buffer), 0, (struct sockaddr *)&client, client_len);
if (n < 0)
{
ERROR("ERROR IN SENDTO()");
}
else
return n;
}
}
NB that time() and ctime() can fail. Pedantic code must check their return values.
I would like to add the functionality of evaluating arithmetic expressions for my simple client server application but do not know how. A client should be asked to input an arithmetic expression and the server should return an evaluation of that expression. The expression should separated into operation(+,-,/,*) and two non negative integer arguments. Server: This must implement an “Arithmetic Service” consisting of a dispatcher and the four operations
add, subtract, multiply and divide which should have identical prototypes:
Status op( int , int , int *); // the last argument is for the result
CLIENT CODE
#include "connection.h"
int clientSocket, z;
SocketAddress serverAddr, clientAddr, rSA;
socklen_t addr_size;
char _message[SIZE], reply[SIZE];
void main(int argc, char **argv)
{
int aPort = IPPORT_RESERVED + getuid();
int rPort = IPPORT_RESERVED + getuid() + 1;
if (argc <= 1)
{
printf("\nUsage: client server_name ??\n example client 127.0.0.1\n");
printf("Use q to close the session.\n");
exit(BAD);
}
z = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
makeReceiverSA(&rSA, rPort);
clientSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (clientSocket < 0)
{
perror("Socket creation failed!");
exit(BAD);
}
else
{
makeLocalSA(&clientAddr);
}
bind(z, (struct sockaddr *)&rSA, sizeof(SocketAddress));
if (bind(clientSocket, (struct sockaddr *)&clientAddr, sizeof(SocketAddress)) != 0)
{
perror("Socket binding failed!");
close(clientSocket);
exit(BAD);
}
printSA(clientAddr);
makeDestSA(&serverAddr, argv[1], aPort);
makeReceiverSA(&rSA, rPort);
printSA(serverAddr);
while (strlen(_message) != 1 && _message[0] != 'q')
{
printf("\nEnter message to send: ");
fgets(_message, SIZE, stdin);
Message m, r;
memcpy(m.data, _message, strlen(_message));
m.length = strlen(_message);
r.length = SIZE;
if (DoOperation(&m, &r, clientSocket, serverAddr) == OK)
{
memcpy(r.data, reply, strlen(reply));
printf("\nResponse: %s\n", r.data);
}
}
}
Status DoOperation(Message *message, Message *reply, int s, SocketAddress serverSA)
{
Status ret;
if (message->length > SIZE)
{
printf("\nError: \n\tCode: %d\n\tMessage: BAD Message Length\n", WRONGLENGTH);
return WRONGLENGTH;
}
ret = UDPsend(s, message, serverSA);
if (ret == BAD)
return BAD;
ret = UDPreceive(z, reply, &rSA);
if (ret == BAD)
return BAD;
return OK;
}
Status UDPsend(int s, Message *m, SocketAddress dest)
{
ssize_t n;
n = sendto(s, m->data, m->length, 0, (struct sockaddr *)&dest, sizeof(SocketAddress));
if (n < 0)
{
printf("\nError: \n\tCode: %d\n\tMessage: Unrecoverable error\n", BAD);
return BAD;
}
if (n != m->length)
return OK;
}
Status UDPreceive(int s, Message *m, SocketAddress *origin)
{
ssize_t n;
socklen_t a = sizeof(SocketAddress);
n = recvfrom(s, reply, SIZE, 0, (struct sockaddr *)&origin, &a);
if (n < 0)
{
printf("\nError: \n\tCode: %d\n\tMessage: Unrecoverable error\n", BAD);
return BAD;
}
if (strlen(reply) > SIZE)
{
printf("\nError: \n\tCode: %d\n\tMessage: BAD Message Length\n", WRONGLENGTH);
return WRONGLENGTH;
}
return OK;
}
HEADER FILE
#include <stdio.h> /* standard C i/o facilities */
#include <unistd.h> /* Unix System Calls */
#include <sys/types.h> /* system data type definitions */
// #include <sys/wait.h> /* System Socket wait definitions */
#include <sys/socket.h> /* socket specific definitions */
#include <netinet/in.h> /* INET constants and stuff */
#include <arpa/inet.h> /* IP address conversion stuff */
#include <string.h>
#include <stdlib.h> /* needed for atoi() */
#include <netdb.h>
struct hostent *gethostbyname() ;
#ifndef SIZE
#define SIZE 1000
#endif
typedef enum {
OK, // operation successful
BAD, // unrecoverable error
WRONGLENGTH // BAD message length supplied
} Status;
typedef struct sockaddr_in SocketAddress;
typedef struct
{
unsigned int length;
unsigned char data[SIZE];
} Message;
extern void printSA(SocketAddress sa) ;
extern void makeDestSA(SocketAddress * sa, char *hostname, int port) ;
extern void makeLocalSA(SocketAddress *sa) ;
extern void receiver(int port) ;
extern void sender(char *message1, char *machine, int port);
extern Status DoOperation(Message *message, Message *reply, int s, SocketAddress serverSA);
extern Status GetRequest(Message *callMessage, int s, SocketAddress *clientSA);
extern Status SendReply(Message *replyMessage, int s, SocketAddress clientSA);
/*
* To return BAD if sendto/recvfrom return negatives
*/
extern Status UDPsend(int s, Message *m, SocketAddress dest);
extern Status UDPreceive(int s, Message *m, SocketAddress *origin);
/*print a socket address */
void printSA(SocketAddress sa)
{
printf("sa = %d, %s, %d\n",
sa.sin_family, inet_ntoa(sa.sin_addr), ntohs(sa.sin_port));
}
/* make a socket address for a destination whose machine and port
are given as arguments */
void makeDestSA(SocketAddress * sa, char *hostname, int port)
{
struct hostent *host;
sa->sin_family = AF_INET;
if((host = gethostbyname(hostname))== NULL) {
printf("Unknown host name\n");
exit(-1);
}
sa->sin_addr = *(struct in_addr *) (host->h_addr);
sa->sin_port = htons(port);
}
/* make a socket address using any of the addressses of this computer
for a local socket on any port */
void makeLocalSA(SocketAddress *sa)
{
sa->sin_family = AF_INET;
sa->sin_port = htons(0);
sa->sin_addr.s_addr = htonl(INADDR_ANY);
}
/* make a socket address using any of the addressses of this computer
for a local socket on given port */
void makeReceiverSA(SocketAddress *sa, int port)
{
sa->sin_family = AF_INET;
sa->sin_port = htons(port);
sa->sin_addr.s_addr = htonl(INADDR_ANY);
}
/*receive two messages via s new socket,
print out the messages received and close the socket
bind to any of the addresses of this computer
using port given as argument */
void receiver(int port)
{
char message1[SIZE], message2[SIZE];
SocketAddress mySocketAddress, aSocketAddress;
int s, n;
socklen_t aLength;
int i;
if((s = socket(AF_INET, SOCK_DGRAM, 0))<0) {
perror("socket failed");
return;
}
makeReceiverSA(&mySocketAddress, port);
if( bind(s, (struct sockaddr *)&mySocketAddress, sizeof(SocketAddress))!= 0){
perror("Bind failed\n");
close(s);
return;
}
printSA(mySocketAddress);
aLength = sizeof(aSocketAddress);
aSocketAddress.sin_family = AF_INET;
if((n = recvfrom(s, message1, SIZE, 0, (struct sockaddr *)&aSocketAddress, &aLength))<0)
perror("Receive 1") ;
else{
printSA(aSocketAddress);
for(i=0; i<n; i++) printf("M:%d", message1[i]);
printf(" Received Message:(%s)length = %d \n",
message1,n);
}
if((n = recvfrom(s, message2, SIZE, 0, (struct sockaddr *)&aSocketAddress, &aLength))<0)
perror("Receive 2");
else {
printf("Received Message:(%s)length = %d \n",
message2,n);
}
close(s);
}
/*do send after receive ready, open socket
bind socket to local internet port
use any of the local computer's addresses
send two messages with given lengths to machine and port
close socket
*/
void sender(char *message1,char *machine, int port)
{
int s, n;
char message[SIZE];
SocketAddress mySocketAddress, yourSocketAddress;
if(( s = socket(AF_INET, SOCK_DGRAM, 0))<0) {
perror("socket failed");
return;
}
/*
if((x = setsockopt(s, SOL_SOCKET, SO_BROADCAST, &arg, sizeof(arg))<0)
perror("setsockopt SO_BROADCAST---");
exit(-1);
*/
makeLocalSA(&mySocketAddress);
if( bind(s, (struct sockaddr *)&mySocketAddress, sizeof(SocketAddress))!= 0){
perror("Bind failed\n");
close (s);
return;
}
printSA(mySocketAddress);
makeDestSA(&yourSocketAddress,machine, port);
printSA(yourSocketAddress);
strcpy(message,message1);
if( (n = sendto(s, message, strlen(message), 0, (struct sockaddr *)&yourSocketAddress,
sizeof(SocketAddress))) < 0)
perror("Send failed\n");
if(n != strlen(message)) printf("sent %d\n",n);
close(s);
}
#include <sys/time.h>
/* use select to test whether there is any input on descriptor s*/
int anyThingThere(int s)
{
unsigned long read_mask;
struct timeval timeout;
int n;
timeout.tv_sec = 1; /*seconds wait*/
timeout.tv_usec = 0; /* micro seconds*/
read_mask = (1<<s);
if((n = select(32, (fd_set *)&read_mask, 0, 0, &timeout))<0)
perror("Select fail:\n");
// else printf("n = %d\n", n);
return n;
}
SERVER CODE
#include "connection.h"
int serverSocket;
SocketAddress serverAddr, clientAddr;
socklen_t addr_size, n;
int i;
char _message[SIZE];
int main(int argc, char **argv)
{
int aPort = IPPORT_RESERVED + getuid();
serverSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (serverSocket < 0)
{
perror("Socket creation failed!\n");
exit(BAD);
}
else
{
makeReceiverSA(&serverAddr, aPort);
}
if (bind(serverSocket, (struct sockaddr *)&serverAddr, sizeof(SocketAddress)) != 0)
{
perror("Socket binding failed!\n");
close(serverSocket);
exit(BAD);
}
printSA(serverAddr);
addr_size = sizeof(clientAddr);
makeDestSA(&clientAddr, "127.0.0.1", aPort+1);
// clientAddr.sin_family = AF_INET;
while (strlen(_message) != 1 && _message[0] != 'q')
{
Message m, r;
char* art = "Message received!";
memcpy(r.data, art, strlen(art));
r.length = strlen(art);
if (anyThingThere(serverSocket) > 0)
if (GetRequest(&m, serverSocket, &clientAddr) == OK)
{
memcpy(_message, m.data, m.length);
printf("\nReceived Message: %s\n", m.data);
Status ret = SendReply(&r, serverSocket, clientAddr);
}
}
}
Status SendReply(Message *replyMessage, int s, SocketAddress clientSA)
{
printSA(clientSA);
Status ret;
ret = UDPsend(s, replyMessage, clientSA);
return OK;
}
Status GetRequest(Message *callMessage, int s, SocketAddress *clientSA)
{
Status ret = UDPreceive(s, callMessage, clientSA);
if (ret == BAD)
return BAD;
if (strlen(_message) > SIZE)
{
printf("\nError: \n\tCode: %d\n\tMessage: BAD Message Length\n", WRONGLENGTH);
return WRONGLENGTH;
}
else
return OK;
}
Status UDPsend(int s, Message *m, SocketAddress dest)
{
ssize_t n;
n = sendto(s, m->data, m->length, 0, (struct sockaddr *)&dest, sizeof(SocketAddress));
if (n < 0)
{
perror("Send Error:");
printf("\nError: \n\tCode: %d\n\tMessage: Unrecoverable error\n", BAD);
return BAD;
}
if (n != m->length)
return OK;
}
Status UDPreceive(int s, Message *m, SocketAddress *origin)
{
ssize_t n;
socklen_t a = sizeof(SocketAddress);
n = recvfrom(s, _message, SIZE, 0, (struct sockaddr *)&origin, &a);
// printf("%ld\n", n);
// printf("%s\n", _message);
// memcpy(&m->data, _message, strlen(_message));
// printf("%s\n", m->data);
// m->length = strlen(_message);
if (n < 0)
{
printf("\nError: \n\tCode: %d\n\tMessage: Unrecoverable error\n", BAD);
return BAD;
}
if (strlen(_message) > SIZE)
{
printf("\nError: \n\tCode: %d\n\tMessage: BAD Message Length\n", WRONGLENGTH);
return WRONGLENGTH;
}
return OK;
}
I've run into a problem with UDP sockets.
For this particular program, a single .c file needs to be both a client to another server (via TCP) and a server/client to itself (executed twice, running on separate servers). It will be running twice at the same time and since it needs to be able to do both the TCP connection (for one type of data) and the UDP connection (for a different type of data) at the same time it needed to be done with threads or forks, but I used threads.
The issue I'm having is the UDP sockets aren't receiving any datagrams from each other. There are no compilation errors and it runs fine, but there's no output other than general debugging print statements. It's getting stuck at the recvfrom commands.
The code below is separated into two parts (again, within the same .c file). The top portion is the server section, and the lower portion is the client section. This is all done WITHIN a thread. I tried creating the socket THEN calling the thread with the client code (the idea was the thread would communicate with the parent but it didn't matter), but it gets the same result. So, for now, the thread just handles the UDP connection and the parent deals with the TCP.
If you need any more explanation, please feel free to ask. This is for a school assignment so I can't give TOO much, but I'll say what I can.
Thank you!
QUICK EDIT: All this code below is doing is just sending hello to the server and back to the client. Further details are not needed.
Assume that argv->stuff is the struct that I passed to the thread and that the user provides the server, IP address, and port when executing.
//----- Server portion of code is below
int cli2_sockfd;
char buffer_cli2[MAXLINE];
char *hello2 = "Hello from client 2";
struct sockaddr_in cli2_addr, client1_addr;
int clis_portno = atoi(argv->port);
clis_portno = clis_portno + 1;
// Creating socket file descriptor
if ( (cli2_sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0 ) {
perror("socket creation failed");
exit(EXIT_FAILURE);
}
memset(&cli2_addr, 0, sizeof(cli2_addr));
memset(&client1_addr, 0, sizeof(client1_addr));
// Filling server information
cli2_addr.sin_family = AF_INET; // IPv4
cli2_addr.sin_addr.s_addr = INADDR_ANY;
cli2_addr.sin_port = htons(clis_portno);
// Bind the socket with the server address
if ( bind(cli2_sockfd, (const struct sockaddr *)&cli2_addr,
sizeof(cli2_addr)) < 0 )
{
perror("bind failed");
exit(EXIT_FAILURE);
}
while(1)
{
int n2;
socklen_t len2;
if((n2 = recvfrom(cli2_sockfd, (char *)buffer_cli2, MAXLINE,
0, ( struct sockaddr *) &client1_addr,
&len2)) < 0)
{
perror("svr recvfrom");
exit(EXIT_FAILURE);
}
buffer_cli2[n2] = '\0';
printf("Client 1: %s\n", buffer_cli2);
if(sendto(cli2_sockfd, (const char *)hello2, strlen(hello2),
MSG_CONFIRM, (const struct sockaddr *) &client1_addr,
len2) < 0)
{
perror("svr sendto");
exit(EXIT_FAILURE);
}
printf("Hello message sent.\n");
}
//----- The client portion of the code is below
int client1_sockfd;
char buffer[MAXLINE];
char *hello1 = "Hello from client 1";
struct sockaddr_in client2_addr;
struct hostent *client_2;
clis_portno = atoi(argv->port);
clis_portno = clis_portno + 1;
// Creating socket file descriptor
if ( (client1_sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0 ) {
perror("socket creation failed");
exit(EXIT_FAILURE);
}
memset(&client2_addr, 0, sizeof(client2_addr));
if((client_2 = gethostbyname(argv->name)) == NULL)
{
perror("cli gethostbyname");
exit(EXIT_FAILURE);
}
bzero((char *) &client2_addr, sizeof(client2_addr));
// Filling Client 2 information
client2_addr.sin_family = AF_INET;
bcopy((char *)client_2->h_addr, (char *)&client2_addr.sin_addr.s_addr, client_2->h_length);
client2_addr.sin_port = htons(clis_portno);
while(1)
{
int n1;
socklen_t len1;
if( sendto(client1_sockfd, (const char *)hello1, strlen(hello1),
0, (const struct sockaddr *) &client2_addr,
sizeof(client2_addr)) < 0)
{
perror("cli sendto");
exit(EXIT_FAILURE);
}
printf("IN THREAD: Hello1 = %s\n", hello1);
if((n1 = recvfrom(client1_sockfd, (char *)buffer, MAXLINE,
MSG_WAITALL, (struct sockaddr *) &client2_addr,
&len1)) < 0)
{
perror("cli recvfrom");
exit(EXIT_FAILURE);
}
buffer[n1] = '\0';
printf("IN THREAD: Client 2 : %s\n", buffer);
}
You are forgetting to initialize len2:
socklen_t len2;
if((n2 = recvfrom(cli2_sockfd, (char *)buffer_cli2, MAXLINE,
0, ( struct sockaddr *) &client1_addr,
&len2)) < 0)
Better:
socklen_t len2 = sizeof(client1_addr);
n2 = recvfrom(cli2_sockfd, (char *)buffer_cli2, MAXLINE,
0, ( struct sockaddr *) &client1_addr,
&len2));
if (n2 < 0)
{
….
Not sure if that's your only issue that's preventing packets from being received.
I cleaned up your code a little and got it to work using port 9999 for server. And having the client connect to localhost. I cleaned up some of those memcpy statements around gethostbyname, some of your struct initialization calls, removed some of the exit calls that could occur for benign errors (including recvfrom errors when the server is offline). That MSG_WAITALL flag looked weird, so I removed that as well.
I got it working Cygwin without any special hacks. I have no doubt it would work in Linux (or any Unix).
You can see it working here in server mode:
And the corresponding window in client mode:
Code here:
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <signal.h>
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/time.h>
#include <stdlib.h>
#include <memory.h>
#include <ifaddrs.h>
#include <net/if.h>
#include <stdarg.h>
#define MAXLINE 260
#define MSG_CONFIRM "Confirm"
void server(unsigned short port)
{
int cli2_sockfd = -1;
char buffer_cli2[MAXLINE] = { 0 };
char *hello2 = "Hello from client 2";
struct sockaddr_in cli2_addr = { 0 }, client1_addr = { 0 };
unsigned short clis_portno = port;
// Creating socket file descriptor
if ((cli2_sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
perror("socket creation failed");
exit(EXIT_FAILURE);
}
// Filling server information
cli2_addr.sin_family = AF_INET; // IPv4
cli2_addr.sin_addr.s_addr = INADDR_ANY;
cli2_addr.sin_port = htons(clis_portno);
// Bind the socket with the server address
if (bind(cli2_sockfd, (const struct sockaddr *)&cli2_addr,
sizeof(cli2_addr)) < 0)
{
perror("bind failed");
exit(EXIT_FAILURE);
}
while (1)
{
int n2;
socklen_t len2 = sizeof(client1_addr);
if ((n2 = recvfrom(cli2_sockfd, (char *)buffer_cli2, MAXLINE,
0, (struct sockaddr *) &client1_addr,
&len2)) < 0)
{
perror("svr recvfrom");
exit(EXIT_FAILURE);
}
buffer_cli2[n2] = '\0';
printf("Client 1: %s\n", buffer_cli2);
if (sendto(cli2_sockfd, (const char *)hello2, strlen(hello2),
0, (const struct sockaddr *) &client1_addr,
len2) < 0)
{
perror("svr sendto");
}
printf("Hello message sent.\n");
}
}
void client(const char* hostname, unsigned short port)
{
int client1_sockfd;
char buffer[MAXLINE];
char *hello1 = "Hello from client 1";
struct sockaddr_in client2_addr = { 0 };
struct hostent *client_2 = NULL;
unsigned short clis_portno = port;
// Creating socket file descriptor
if ((client1_sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
perror("socket creation failed");
exit(EXIT_FAILURE);
}
if ((client_2 = gethostbyname(hostname)) == NULL)
{
perror("cli gethostbyname");
exit(EXIT_FAILURE);
}
// Filling Client 2 information
client2_addr.sin_family = AF_INET;
client2_addr.sin_port = htons(clis_portno);
memcpy(&client2_addr.sin_addr, client_2->h_addr, 4);
while (1)
{
int n1;
if (sendto(client1_sockfd, (const char *)hello1, strlen(hello1),
0, (const struct sockaddr *) &client2_addr,
sizeof(client2_addr)) < 0)
{
perror("cli sendto");
exit(EXIT_FAILURE);
}
printf("IN THREAD: Hello1 = %s\n", hello1);
socklen_t len1 = sizeof(client2_addr);
if ((n1 = recvfrom(client1_sockfd, (char *)buffer, MAXLINE,
0, (struct sockaddr *) &client2_addr,
&len1)) < 0)
{
perror("cli recvfrom");
}
else
{
buffer[n1] = '\0';
printf("IN THREAD: Client 2 : %s\n", buffer);
}
sleep(1);
}
}
int main(int argc, char** argv)
{
if ((argc > 1) && (strcmp(argv[1], "s") == 0))
{
printf("Running in server mode\n");
server(9999);
}
else
{
printf("Running in client mode\n");
client("localhost", 9999);
}
return 0;
}
I have written a proxy that accepts connections from host1 and forwards the connection toward server2.
I accept a connection and then I start two threads to handle the connections... One thread to receive from host 1 and send to server2, and another thread to receive form server2 and send to host1.
My program compiles with no errors, and when I run it and connect host 1 my program fails at the function WRITE after some short time with no error.
The connection is OK, it just fails after short period of time, before write.
Also you can find the written function that I am using.
The code is failing at the CONTROLLER thread, when the controller is writing to the socket.
Why does the program fail with no error message at all?
/*
* File Server0.c
* ECHO TCP SERVER with the following features:
* - Gets port from keyboard
* - SEQUENTIAL: serves one client at a time
*/
#define _POSIX_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <inttypes.h>
#include "mysocket.h"
#include <arpa/inet.h>
#include <fcntl.h> // for open
#include <unistd.h> // for close
#include <sys/types.h>
#include <signal.h>
#include <sys/wait.h>
#include <pthread.h> /* POSIX threads */
#define RBUFLEN 16384
/* FUNCTION PROTOTYPES */
int mygetline(char * line, size_t maxline, char *prompt);
int writen(SOCKET, char *, size_t);
void *mininet(void *);
void *controller(void *);
SOCKET s,s1[100],d[100];
int y=0,z=0;
int main()
{
uint16_t lport_n, lport_h;
int result;
socklen_t addrlen;
struct sockaddr_in saddr, caddr;
//fd_set readfds;
SOCKET conn_request_skt;
int bklog = 2,t=0;
pthread_t tid1[100];
pthread_t tid[100];
/* Initialize socket API if needed */
SockStartup();
/* input server port number */
lport_h=8888;
lport_n = htons(lport_h);
/* create the MININET socket */
printf("Creating first socketn");
s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (s == INVALID_SOCKET)
err_fatal("socket() failed");
printf("done, socket number %un",s);
/* bind the MININET socket to any local IP address */
saddr.sin_family = AF_INET;
saddr.sin_port = lport_n;
saddr.sin_addr.s_addr = INADDR_ANY;
showAddr("Binding to address first socket", &saddr);
result = bind(s, (struct sockaddr *) &saddr, sizeof(saddr));
if (result == -1)
err_fatal("bind() failed");
printf("done.n");
/* listen on MININET socket */
printf ("Listening at socket %d with backlog = %d n",s,bklog);
result = listen(s, bklog);
if (result == -1)
err_fatal("listen() failed");
printf("done.n");
conn_request_skt=s;
/* accept next connection from mininet */
for(;;)
{
addrlen = sizeof(struct sockaddr_in);
z++;
y++;
t++;
d[t] = accept(conn_request_skt, (struct sockaddr *) &caddr, &addrlen);
if (d[t] == INVALID_SOCKET)
err_fatal("accept() failed");
showAddr("Accepted connection from", &caddr);
printf("new accepted connection socket: %un",d[t]);
/* serve the client on socket s */
pthread_create(&tid[t], NULL, mininet, &t);
pthread_create(&tid1[t], NULL, controller, &t);
sleep(1);
}
exit(0);
}
void *mininet (void *arg)
{
char buf[RBUFLEN]; /* reception buffer */
int n,t,k;
t=y;
k=z;
printf("MININET: m is: %d, c is: %d n ", t,k);
/* main server loop */
for (;;)
{
printf("MININET receiving on socket: %un",d[t]);
n=recv(d[t], buf, RBUFLEN-1, 0);
if (n < 0)
{
printf("MININET Read errorn");
closesocket(d[t]);
printf("MININET Socket %d closedn", d[t]);
return NULL;
}
else if (n==0)
{
printf("Connection closed by MININET on socket %dn",d[t]);
closesocket(d[t]);
break;
}
else
{
printf("Received line from MININET socket %03d :n", d[t]);
buf[n]=0;
printf("[%s]n",buf);
printf("MINET WRITING TO: %un",s1[k]);
if(writen(s1[k], buf, n) != n)
printf("Write error while replying TO CONTROLERn");
else
printf("Reply sent towards CONTROLERn");
}
}
return NULL;
}
void *controller (void *arg)
{
char buf[RBUFLEN]; /* reception buffer */
uint16_t lport_n1, lport_h1; /* port where the server listens (net/host byte ord resp.) */
int result, n,t,k;
struct sockaddr_in saddr1; /* server and client address structures */
t=y;
k=z;
printf("CONTROLLER: m is: %d, c is: %d n ", t,k);
/* Initialize socket API if needed */
SockStartup();
lport_h1=6633;
lport_n1 = htons(lport_h1);
printf("Creating CONTROLLER socketn");
s1[k] = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (s1[k] == INVALID_SOCKET)
err_fatal("socket() failed");
printf("done, socket number %un",s1[k]);
/* bind the socket to any local IP address */
saddr1.sin_family = AF_INET;
saddr1.sin_port = lport_n1;
saddr1.sin_addr.s_addr = INADDR_ANY;
/* connect */
showAddr("Connecting to target CONTROLER address", &saddr1);
result = connect(s1[k], (struct sockaddr *) &saddr1, sizeof(saddr1));
if (result == -1)
err_fatal("connect() failed");
printf("done.n");
/* main server loop */
for (;;)
{
printf("CONTROLER receiving on socket: %un",s1[k]);
n=recv(s1[k], buf, RBUFLEN-1, 0);
if (n < 0)
{
printf("CONTROLER Read errorn");
closesocket(s1[k]);
printf("Socket %d closedn", s1[k]);
return NULL;
}
else if (n==0)
{
printf("Connection closed by CONTROLER on socket %dn",s1[k]);
closesocket(s1[k]);
return NULL;
}
else
{
printf("Received line from CONTROLER socket %03d :n", s1[k]);
buf[n]=0;
printf("[%s]n",buf);
printf("CONTROLER writing on socket: %un",d[t]);
if(writen(d[t], buf, n) != n)
printf("Write error while replying TO MININETn");
else
printf("Reply sent towards MININETn");
}
}
return NULL;
}
/* Gets a line of text from standard input after having printed a prompt string Substitutes end of line with ''
Empties standard input buffer but stores at most maxline-1 characters in the passed buffer
*/
int mygetline(char *line, size_t maxline, char *prompt)
{
char ch;
size_t i;
printf("%s", prompt);
for (i=0; i< maxline-1 && (ch = getchar()) != 'n' && ch != EOF; i++)
*line++ = ch;
*line = '';
while (ch != 'n' && ch != EOF)
ch = getchar();
if (ch == EOF)
return(EOF);
else
return(1);
}
/* Writes nbytes from buffer ptr to stream socket s */
int writen(SOCKET s, char *ptr, size_t nbytes)
{
size_t nleft;
ssize_t nwritten;
for (nleft=nbytes; nleft > 0; )
{
nwritten = send(s, ptr, nleft, 0);
if (nwritten <=0)
return (nwritten);
else
{
nleft -= nwritten;
ptr += nwritten;
}
}
return (nbytes - nleft);
}
I'm trying make asynchronous server listener with C++ .I can write simple listener without asynchronous but now i have problem with CreateThread.
For example if client has been connected console gives me result about this + sniffer can fix it, after 10 sec client must send me again same packet with different data. my console does not gives me result about that packet but sniffer can see that packet... please if anyone can see my problem explain me.
#include <winsock2.h>
#include <windows.h>
#include <fcntl.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <stdio.h>
DWORD WINAPI SocketHandler(void*);
int main(int argv, char** argc){
//The port you want the server to listen on
int host_port = 7878;
//Initialize socket support WINDOWS ONLY!
unsigned short wVersionRequested;
WSADATA wsaData;
int err;
wVersionRequested = MAKEWORD( 2, 2 );
err = WSAStartup( wVersionRequested, &wsaData );
if ( err != 0 || ( LOBYTE( wsaData.wVersion ) != 2 ||
HIBYTE( wsaData.wVersion ) != 2 )) {
fprintf(stderr, "Could not find useable sock dll %d\n",WSAGetLastError());
}
//Initialize sockets and set any options
int hsock;
int * p_int ;
hsock = socket(AF_INET, SOCK_STREAM, 0);
if(hsock == -1){
printf("Error initializing socket %d\n",WSAGetLastError());
}
p_int = (int*)malloc(sizeof(int));
*p_int = 1;
if( (setsockopt(hsock, SOL_SOCKET, SO_REUSEADDR, (char*)p_int, sizeof(int)) == -1 )||
(setsockopt(hsock, SOL_SOCKET, SO_KEEPALIVE, (char*)p_int, sizeof(int)) == -1 ) ){
printf("Error setting options %d\n", WSAGetLastError());
free(p_int);
}
free(p_int);
//Bind and listen
struct sockaddr_in my_addr;
my_addr.sin_family = AF_INET ;
my_addr.sin_port = htons(host_port);
memset(&(my_addr.sin_zero), 0, 8);
my_addr.sin_addr.s_addr = INADDR_ANY ;
if( bind( hsock, (struct sockaddr*)&my_addr, sizeof(my_addr)) == -1 ){
fprintf(stderr,"Error binding to socket, make sure nothing else is listening on this port %d\n",WSAGetLastError());
}
if(listen( hsock, 10) == -1 ){
fprintf(stderr, "Error listening %d\n",WSAGetLastError());
}
//Now lets to the server stuff
int* csock;
sockaddr_in sadr;
int addr_size = sizeof(SOCKADDR);
while(true){
printf("waiting for a connection\n");
csock = (int*)malloc(sizeof(int));
if((*csock = accept( hsock, (SOCKADDR*)&sadr, &addr_size))!= INVALID_SOCKET ){
printf("Received connection from %s",inet_ntoa(sadr.sin_addr));
CreateThread(0,0,&SocketHandler, (void*)csock , 0,0);
}
else{
fprintf(stderr, "Error accepting %d\n",WSAGetLastError());
}
}
}
DWORD WINAPI SocketHandler(void* lp){
int *csock = (int*)lp;
char buffer[1024];
int buffer_len = 1024;
int bytecount;
memset(buffer, 0, buffer_len);
if((bytecount = recv(*csock, buffer, buffer_len, 0))==SOCKET_ERROR){
fprintf(stderr, "Error receiving data %d\n", WSAGetLastError());
}
printf("Received bytes %d\n Received string \"%s\"\n", bytecount, buffer);
char buff[1] = {0x11};
if((bytecount = send(*csock, buff, 1, 0))==SOCKET_ERROR){
fprintf(stderr, "Error sending data %d\n", WSAGetLastError());
}
printf("Sent bytes: %d. Send Message: %s\n ", bytecount,buff);
free(csock);
}
A race condition is most likely the cause of your problem. You declare csock on the stack and then pass it to SocketHandler. The trouble is, it's quite possible that the value of csock changes before SocketHandler gets it and makes a copy since csock = accept() is in a loop. The solution is to dynamically allocate csock using malloc and then have SocketHandler free it.
Even if this isn't the cause of your specific problem, this code can never be reliable until you fix that.
CreateThread doesn't loop or anything. You need to put the code in there inside a loop. Something like this:
DWORD WINAPI SocketHandler(void* lp) {
for(;;) {
/* Code here */
}
return EXIT_SUCCESS;
}