Winsock2 thread arguments throw exception access violation - c

I am programming a UDP server-client program with WinSock2.h, where the needed arguments (SOCKET, sockaddr_in) to respective threads are passed to the thread through a struct.
My receive function keeps throwing an exception whenever it gets to the recvfrom() part, but only when I'm debugging the program. If I start it without debugger, it doesn't show me any errors nor stops the program running. This exception only happens at the server's side. Also, the recvfrom() error checking keeps throwing error 10022 on the client's side, but as far as I understand, this is caused by not having bind() on the client side.
Does the server side have the problem with bind() being in another function or are my pointers somewhere wrong? I don't have any other ideas why is it only throwing the exception on the server side.
typedef struct thread_args {
struct sockaddr_in sockaddr;
SOCKET socket;
int keep_alive_count;
}THREAD_ARG;
void* receive_packets(void* arguments) {
THREAD_ARG* args = (THREAD_ARG*)arguments;
struct sockaddr_in* from;
char buffer[MAX_FRAGMENTATION + sizeof(HEADER)];
HEADER* message;
while (1) {
memset(buffer, "\0", MAX_FRAGMENTATION + sizeof(HEADER));
//this is where I get the exception thrown
if (recvfrom(args->socket, buffer, sizeof(buffer), 0, (struct sockaddr*) & from, sizeof(from)) == SOCKET_ERROR) {
printf("recvfrom() failed, error code: %d\n", WSAGetLastError());
exit(RECVFAIL);
}
message = (HEADER*)buffer;
char flag = message->flags;
}
}
return 0;
}
int client(THREAD_ARG* args) {
u_short port;
char ip[50];
struct sockaddr_in client_sock;
void* return_value1, *return_value2;
getchar();
printf("Please enter the IP address you would like to communicate with:\n");
gets(IP);
printf("Please enter the port number you would like to communicate with:\n");
scanf("%hu", &port);
client_sock.sin_family = AF_INET;
client_sock.sin_addr.s_addr = inet_addr(IP);
client_sock.sin_port = htons(port);
args->sockaddr = client_sock;
pthread_t send_thread, receive_thread, keep_alive_thread;
pthread_create(&send_thread, NULL, send_packets, args);
pthread_create(&receive_thread, NULL, receive_packets, args);
pthread_create(&keep_alive_thread, NULL, keep_alive, args);
pthread_join(send_thread, &return_value1);
pthread_join(receive_thread, &return_value2);
pthread_join(keep_alive_thread, NULL);
return 0;
}
int server(THREAD_ARG* args) {
u_short port;
int valid;
struct sockaddr_in server_sock;
void* return_value1, * return_value2;
printf("Please enter the port number you would like to listen on:\n");
scanf("%hu", &port);
server_sock.sin_family = AF_INET;
server_sock.sin_addr.s_addr = INADDR_ANY;
server_sock.sin_port = htons(port);
if(bind(args->socket, (struct sockaddr_in*) & server_sock, sizeof(server_sock)) == SOCKET_ERROR) {
printf("Bind failed, error code: %d\n", WSAGetLastError());
return 1;
}
printf("Bind done\n");
args->sockaddr = server_sock;
pthread_t receive_thread;
pthread_create(&receive_thread, NULL, receive_packets, args);
pthread_join(receive_thread, &return_value2);
}
int main() {
WSADATA was;
SOCKET sock;
char choice;
THREAD_ARG* args;
printf("WinSock initialisation.\n");
if (WSAStartup(MAKEWORD(2, 2), &wsa) != 0) {
printf("WinSock initialisation failed. Error code: %d\n", WSAGetLastError());
return 1;
}
printf("WinSock initialised.");
if ((sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == INVALID_SOCKET) {
printf("Couldn't create socket: %d\n", WSAGetLastError());
}
printf("Socket created.\n");
printf("Would you like to be a server or a client?\n");
printf("1 - Server\n");
printf("2 - Client\n");
printf("0 - Exit\n");
args = (THREAD_ARG*)malloc(sizeof(THREAD_ARG));
args->socket = sock;
switch (choice = getchar())
{
case '0':
return 0;
case '1':
server(args);
break;
case '2':
client(args);
break;
default:
printf("Please choose from above\n");
}
return 0;
}

struct sockaddr_in* from;
char buffer[MAX_FRAGMENTATION + sizeof(HEADER)];
HEADER* message;
You have a problem here. You allocate only a sockaddr_in*. But you need an actual sockaddr_in to hold the address.
while (1) {
memset(buffer, "\0", MAX_FRAGMENTATION + sizeof(HEADER));
Here, the second parameter to memset is wrong. It's supposed to be the value to set to, not a pointer to a value.
if (recvfrom(args->socket, buffer, sizeof(buffer), 0, (struct sockaddr*) & from, sizeof(from)) == SOCKET_ERROR) {
Here, you cast a struct sockaddr_in ** to a struct sockaddr *, throwing away a level of indirection. That doesn't make any sense. And the last parameter, sizeof(from) is the size of a pointer. That's not right.
THREAD_ARG* args;
...
args = (THREAD_ARG*)malloc(sizeof(THREAD_ARG));
args->socket = sock;
Why this weird indirection? Why not just THREAD_ARD args; and get rid of the malloc and -> stuff?

Related

Multipleclient Server: quitfunction

I have some problems with my Server/Client.
If multiple people connect to my server, and one of them quit the connection to the server, all other, which are also connected to the server, lose their connection to.
void *connection_handler(void *);
extern int check_err_buffer(int sock);
extern error_t *error_buffer;
extern invalid_user_input_t invalid_user_input;
regex_t regex;
int main(int argc, char *argv[]) {
//init KVS
init();
int socket_desc, client_sock, c, *new_sock;
struct sockaddr_in server, client;
//Create socket
socket_desc = socket(AF_INET, SOCK_STREAM | O_NONBLOCK, 0);
int opts;
opts = fcntl(socket_desc,F_GETFL);
opts = opts & (~O_NONBLOCK);
fcntl(socket_desc,F_SETFL,opts);
if (socket_desc == -1) {
printf("Could not create socket");
}
puts("Socket created");
//Prepare the sockaddr_in structure
server.sin_family = AF_INET;
server.sin_addr.s_addr = INADDR_ANY;
server.sin_port = htons(8503);
//Bind
if (bind(socket_desc, (struct sockaddr *) &server, sizeof(server)) < 0) {
//print the error message
perror("bind failed. Error");
return 1;
}
puts("bind done");
//Listen
listen(socket_desc, 3);
//Accept and incoming connection
puts("Waiting for incoming connections...");
c = sizeof(struct sockaddr_in);//Accept and incoming connection
puts("Waiting for incoming connections...");
c = sizeof(struct sockaddr_in);
while (1) {
puts("waiting for client...");
client_sock = accept(socket_desc, (struct sockaddr *) &client, (socklen_t * ) & c);
puts("Connection accepted");
pthread_t sniffer_thread;
new_sock = malloc(1);
*new_sock = client_sock;
pthread_create(&sniffer_thread, NULL, connection_handler, (void *) new_sock);
//Now join the thread , so that we dont terminate before the thread
//pthread_join(sniffer_thread, NULL);
puts("Handler assigned");
}
if (client_sock < 0) {
perror("accept failed");
return 1;
}
return 0;
}
In the main function I accept the different connection from the clients.
I have more functions, which I didn't put in, because they are not so relevant for this problem.
In the second part I will handle some cases. I look if the client type the letter 'q', if it's true, I will close the connection with close().
But in all cases, it close the server, and all connections are lost.
/*
* This will handle connection for each client
* */
void *connection_handler(void *socket_desc) {
//Get the socket descriptor
int sock = *(int *) socket_desc;
char *message, client_message[3000];
puts("sending welcome msg to client...");
write(sock, message, 3000);
int reti;
//compile a regexp that checks for valid user input
regcomp(&regex, "([dg] [0-9]+)|([v] .+)|(p [0-9]+ .+)|q", REG_EXTENDED);
//Receive a message from client
char *input[3];
while(1){
//wait for some client input
recv(sock, client_message, 2000, 0);
//check the input with the regexp
reti = regexec(&regex, client_message, 0, NULL, REG_EXTENDED);
if (!reti) {
//tokenize the client input with \n as a delim char
char *token = strtok(client_message, " ");
int i = 0;
while (token) {
input[i] = token;
token = strtok(NULL, " ");
i++;
}
//quit operation
if (strcmp(input[0], "q") == 0) {
//if a client quits, the server dies. TODO: fix
puts("quitting");
//free(socket_desc);
close(socket_desc);
return 0;
}
//user input does not match regexp, try again..
} else if (reti == REG_NOMATCH) {
error_buffer = invalid_user_input;
check_err_buffer(sock);
usleep(100);
write(sock, " ", 2);
}
}
//Free the socket pointer
free(socket_desc);
return 0;
}
On the client side i test if message[0] == 'q' and I close the socket.
I would be very happy if i will get some help or hints to solve this problem. Thank you
As here
new_sock = malloc(1);
the code allocates 1 byte only, this following line
*new_sock = client_sock;
writes to invalid memory, as an int is assigned, and sizeof int bytes are written to where new_sock points. By definition sizeof int is at least 2, probably more, With this undefined behaviour is invoked. Anything may happen from then on.
To fix this do
new_sock = malloc(sizeof *new_sock);
instead.
Inspecting the return value of functions is debugging for free. close(socket_desc); is nonsense and definitely would return -1 and set errno to EBADFD.
Replace
close(socket_desc);
by
if (-1 == close(socket_desc))
{
perror("close() falied");
}
to see how the code as it stand fails.

Worker thread exits some time later

Here is a simple echo program using sockets and multi threads, it compiles and runs well in my Ubuntu if the client(via telnet) and server run on the same machine, but when I remotely connect to the server via telnet from another machine, it initially runs well(echos my message back every time), but some time later, there is no echo anymore even the telnet session is still alive, i am not sure where the problem is, can someone give some hits on this? I am new to multi thread programming and socket programming, learning on that.
#define ERROR -1
#define MAX_CLIENTS 2
#define MAX_DATA 1024
void* worker(void* sockId)
{
int socketId = *(int*)sockId;
int data_len = 1;
char data[MAX_DATA];
while(data_len > 0)
{
data_len = recv(socketId, data, MAX_DATA, 0);
if (data_len > 0)
{
send(socketId, data, data_len, 0);
data[data_len] = '\0';
printf("Sent message: %s", data);
}
}
printf("Client disconnected\n");
close(socketId);
}
int main(int argc, char* argv[])
{
if (argc <= 1)
{
printf("missing argument: port\n");
exit(-1);
}
struct sockaddr_in server;
struct sockaddr_in client;
int sock;
int new_connection;
int sockaddr_len = sizeof(struct sockaddr_in);
if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == ERROR)
{
perror("server socket: ");
exit(-1);
}
server.sin_family = AF_INET;
server.sin_port = htons(atoi(argv[1]));
server.sin_addr.s_addr = INADDR_ANY;
bzero(&server.sin_zero, 8);
if ((bind(sock, (struct sockaddr*)&server, sockaddr_len)) == ERROR)
{
perror("bind: ");
exit(-1);
}
if ((listen(sock, MAX_CLIENTS)) == ERROR)
{
perror("listen: ");
exit(-1);
}
while(1)
{
if ((new_connection = accept(sock, (struct sockaddr*)&client, &sockaddr_len)) == ERROR)
{
perror("accpet: ");
exit(-1);
}
printf("New Client connected from port: %d and IP: %s\n", ntohs(client.sin_port), inet_ntoa(client.sin_addr));
pthread_t thread;
pthread_create(&thread, NULL, worker, (void*)&new_connection);
pthread_detach(thread);
}
close(sock);
pthread_exit(NULL);
return 0;
}
Add some logging and you'll probably find that your code is blocked in send. You use naive, sequential I/O, so if the other end of the connection stops reading data, soon you do too.

Implementation of custom message logger for windows : reports 10049 when ntwk cable unplugged

Trying to develop a simple/small syslog server for windows.
This implementation is just to store LOGS in the same machine from 2 other processes of same machine.
Wanted this to be similar to LINUX implementation.Started to use UDP DATAGRAM to send data between processes.
It is working as expected. However, it has been noticed that when NETWORK cable is unplugged the messages are not reaching to the server from client process application.
The client process reports 10049 error (When network cable is unplugged)
Request some guidance how to make this work between local process. Since, all my process run in local machine.
SERVER END LISTEN CODE:
int main(int argc,char *argv[])
{
SOCKET s;
FILE *fp;
struct sockaddr_in server, si_other;
int slen , recv_len;
char buf[BUFLEN];
WSADATA wsa;
struct stat sts;
char fileNameWithPath[512]={'\0'};
int status;
printf("ARGC %d\n",argc);
char a[10];
strcpy(logBasePath,"C:\\log\\");
if(argc == 1)
{
//parseSyslogConfiguration();
if (loggingLevel > 4)
loggingLevel=DEBUG_LOG;
}
else
{
memset(a,0,sizeof(a));
strncpy(a,argv[1],1);
int isnum=isdigit(a[0]);
printf("len argv : %d , isdigit : %d\n",strlen(argv[1]),isnum);
//parseSyslogConfiguration();
if(strlen(argv[1]) == 1 && isnum == 1)
{
loggingLevel = atoi(argv[1]);
if (loggingLevel > 4)
loggingLevel=DEBUG_LOG;
printf("Current Log level initaited : %d",loggingLevel);
}
else
{
loggingLevel=DEBUG_LOG;
printf("Invalid arg (%s)for syslog server setting log level to DEBUG\n",argv[1]);
printf("Values can be from : 0-4 \n");
}
}
if(buf[strlen(logBasePath)-1] != '\\')
{
printf("ADDING END SLASH\n");
strncat(logBasePath,"\\",1);
}
else
printf("NOT ADDING END SLASH\n");
//g_thread_init(NULL);
//write_mutex = g_mutex_new();
slen = sizeof(si_other) ;
getdatetime(&dateinfo);
strcpy(logFileName,"syslog");
memset(fileNameWithPath,0,sizeof(fileNameWithPath));
strcat(fileNameWithPath,logBasePath);
strcat(fileNameWithPath,logFileName);
//strcat(fileNameWithPath,logFileName,logBasePath,"syslog");
status = stat(fileNameWithPath, &sts);
if(errno == ENOENT)
{
fp = fopen(fileNameWithPath, "a+");
logMessage(fp,dateinfo.syslogTimeFormat,"LOGROTATE","[origin software='TEST']",0);
fclose(fp);
}
getdatetime(&dateinfo);
setSyslogFileDate(logBasePath);
//Initialise winsock
printf("\nInitialising Winsock...");
if (WSAStartup(MAKEWORD(2,2),&wsa) != 0)
{
printf("Failed. Error Code : %d",WSAGetLastError());
exit(EXIT_FAILURE);
}
printf("Initialised.\n");
//Create a socket
if((s = socket(AF_UNIX , SOCK_DGRAM , 0 )) == INVALID_SOCKET)
{
printf("Could not create socket : %d" , WSAGetLastError());
}
printf("Socket created.\n");
//Prepare the sockaddr_in structure
server.sin_family = AF_UNIX;
server.sin_addr.s_addr = INADDR_ANY;
server.sin_port = htons( PORT );
//Bind
if( bind(s ,(struct sockaddr *)&server , sizeof(server)) == SOCKET_ERROR)
{
printf("Bind failed with error code : %d" , WSAGetLastError());
exit(EXIT_FAILURE);
}
puts("Bind done");
//msgQueueId = g_queue_new();
//g_queue_init(msgQueueId);
// syslogFileWriteThreadId = g_thread_create(ProcessLogMsgfunc, NULL, TRUE, &error);
// syslogRotateThreadId = g_thread_create(syslogRotateMonitor, NULL, TRUE, &error);
//keep listening for data
while(1)
{
fflush(stdout);
memset(buf,'\0', BUFLEN);
if ((recv_len = recvfrom(s, buf, BUFLEN, 0, (struct sockaddr *) &si_other, &slen)) == SOCKET_ERROR)
{
printf("recvfrom() failed with error code : %d" , WSAGetLastError());
exit(EXIT_FAILURE);
}
LOGSTRUCT *qMsg = NULL;
memset(&message,0,sizeof(LOGSTRUCT));
qMsg = malloc(sizeof(LOGSTRUCT));
memset(qMsg,0,sizeof(LOGSTRUCT));
memcpy(qMsg,&buf,sizeof(LOGSTRUCT));
PostMessageQ(qMsg);
}
// g_mutex_free(write_mutex);
// g_queue_free(msgQueueId);
closesocket(s);
WSACleanup();
// g_thread_join(syslogFileWriteThreadId);
// g_thread_join(syslogRotateThreadId);
return 0;
}
CLENT SIDE IMPLEMENTATION:
#include<stdio.h>
#include<winsock2.h>
//#include <glib.h>
#define DEBUG_LOG 0
#define TRACE_LOG 1
#define WARNING_LOG 2
#define ERROR_LOG 3
#define FATAL_LOG 4
#pragma comment(lib,"ws2_32.lib") //Winsock Library
#define SERVER "127.0.0.1" //ip address of udp server
#define BUFLEN 4096 //Max length of buffer
#define PORT 514 //The port on which to listen for incoming data
#define RUN_SERVER 1
struct sockaddr_in si_other;
int s;
GMutex *write_mutex = NULL;
static char appLogName[128] = {'0'};
typedef enum{
LOGINIT,
LOGMESSAGE,
LOGTRACE,
LOGEXIT
}logCommand;
typedef struct
{
logCommand command;
int logLevel;
int pid;
char appName[128];
char loggerMessage[3200];
}LOGSTRUCT, *LPLOGSTRUCT;
int log_init(char *infoName,int level)
{
int ret=0;
WSADATA wsa;
//if(write_mutex == NULL)
//{
//g_thread_init(NULL);
//write_mutex = g_mutex_new();
//Initialise winsock
if(strlen(infoName) == 0 && strlen(appLogName) == 0)
{
strcpy(appLogName,"ATM");
}
else
{
strcpy(appLogName,infoName);
}
//create socket
if ( (s=socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) == SOCKET_ERROR)
{
printf("socket() failed with error code : %d" , WSAGetLastError());
//exit(EXIT_FAILURE);
return -1;
}
//int nOpt=1;
//setsockopt(s, SOL_SOCKET, SO_BROADCAST, (char*)&nOpt, sizeof(int));
//setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, (char*)&nOpt, sizeof(int));
//setup address structure
memset((char *) &si_other, 0, sizeof(si_other));
si_other.sin_family = AF_INET;
si_other.sin_port = htons(PORT);
si_other.sin_addr.S_un.S_addr = INADDR_ANY;
//si_other.sin_addr.S_un.S_addr = inet_addr(SERVER);
// si_other.sin_addr.S_un.S_addr = INADDR_BROADCAST ;
// si_other.sin_addr.s_addr = INADDR_ANY;
//}
return 0;
}
void log_exit()
{
RUN_SERVER=0;
closesocket(s);
WSACleanup();
}
void ms_log(char *buf,int priority)
{
debug_log(buf,priority);
}
void debug_log(char *buf,int priority)
{
//g_mutex_lock(write_mutex);
int ret = 0;
LOGSTRUCT log;
memset(&log,0,sizeof(LOGSTRUCT));
log.command=LOGMESSAGE;
log.logLevel=priority;
log.pid = GetCurrentProcessId();
if(strlen(appLogName))
{
strcpy(log.appName,appLogName);
}
if(strlen(buf))
{
strcpy(log.loggerMessage,buf);
ret=sendDataPacket(&log , sizeof(LOGSTRUCT));
}
//g_mutex_unlock(write_mutex);
}
int sendDataPacket(LOGSTRUCT *data , int dataLength)
{
BOOL bResult;
DWORD cbBytes;
int slen;
slen=sizeof(si_other);
if (sendto(s, data, dataLength , 0 , (struct sockaddr *) &si_other, slen) == SOCKET_ERROR)
{
printf("sendto() failed with error code : %d" , WSAGetLastError());
return -1;
}
return 0;
}
int main(void)
{
char buf[BUFLEN];
char message[BUFLEN];
WSADATA wsa;
LOGSTRUCT log;
//start communication
printf("\nInitialising Winsock...");
if (WSAStartup(MAKEWORD(2,2),&wsa) != 0)
{
printf("Failed. Error Code : %d",WSAGetLastError());
//exit(EXIT_FAILURE);
return -2;
}
printf("Initialised.\n");
log_init("TESTVEN",1);
while(RUN_SERVER)
{
printf("Enter message : ");
gets(message);
log.command = LOGMESSAGE;
strcpy(log.appName,"TESTAPP");
log.logLevel=DEBUG_LOG;
log.pid=GetCurrentProcessId();
strcpy(log.loggerMessage,message);
sendDataPacket(&log,sizeof(LOGSTRUCT));
//send the message
}
log_exit();
return 0;
}
Error code 10049 : WSAEADDRNOTAVAIL: Cannot assign requested address.
The requested address is not valid in its context. This normally results from an attempt to bind to an address that is not valid for the local computer. This can also result from connect, sendto, WSAConnect, WSAJoinLeaf, or WSASendTo when the remote address or port is not valid for a remote computer (for example, address or port 0).
So can happen with sendto as well. The remote address IP_ADDR_ANY is not a valid address any more on cable plugout?
If its on same machine, try 127.0.0.1 on server code as well?

Invalid argument in sendto

I have two programs which communicate with each other.
Client: First send the message then listen for reply.
Server: Listen for reply and then send message.
Im able to send message from client prefectly and listen in server too. But problem comes when I try to send message from server.
struct hostent *gethostbyname();
typedef struct Message {
unsigned int length;
unsigned char data[SIZE];
} Message;
typedef struct sockaddr_in SocketAddress;
int fileDesc;
int aLength;
void main(int argc, char **argv) {
Message callMsg, rep;
aLength = 0;
SocketAddress clientSAMain, serverSAMain;
int port = RECIPIENT_PORT;
if ((fileDesc = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
perror("socket failed");
//return BAD;
}
makeReceiverSA(&serverSAMain, port);
if (bind(fileDesc, (struct sockaddr *) &serverSAMain,
sizeof(struct sockaddr_in)) != 0) {
perror("Bind failed\n");
close(fileDesc);
//return BAD;
}
clientSAMain.sin_family = AF_INET;
aLength = sizeof(serverSAMain);
GetRequest(&callMsg, port, &clientSAMain);
SendReply(&rep, port, clientSAMain);
close(fileDesc);
}
void GetRequest(Message *callMessage, int s, SocketAddress *clientSA) {
//SocketAddress serverSA;
int n;
int i;
if ((n = recvfrom(fileDesc, callMessage->data, SIZE, 0,
(struct sockaddr *) &clientSA, &aLength)) < 0)
perror("Receive 1");
else
printf("\n Received Message:(%s)length = %d \n", callMessage->data, n);
}
}
void SendReply(Message *replyMessage, int s, SocketAddress clientSANew) {
printf("Enter a reply:");
scanf("%s", replyMessage->data);
if ((n = sendto(fileDesc, replyMessage->data, sizeof(replyMessage->data), 0,
(struct sockaddr *) &clientSANew, sizeof(struct sockaddr_in))) < 0)
perror("Send Failed in Server\n");
if (n != strlen(replyMessage->data))
printf("sent %d\n", n + 1);
}
/* make a socket address using any of the addressses of this computer
for a local socket on given port */
void makeReceiverSA(struct sockaddr_in *sa, int port) {
sa->sin_family = AF_INET;
sa->sin_port = htons(port);
sa->sin_addr.s_addr = htonl(INADDR_ANY);
}
//If i place the sendreply function code in GetRequest function it is working fine. Can anyone help me with this. I have been trying all the possible way but did not find a solution. Work under progress for me so spare me if it is silly question.
PS:Edited out all the unnecessary code.
recvfrom(fileDesc, callMessage->data, SIZE, 0,
(struct sockaddr *) &clientSA, &aLength)
Because clientSA is a pointer, the above will overwrite the pointer variable and the memory after it. &clientSA in the above call should be clientSA.

UDP multi-client chat server

I have a multi-client chat server and for some reason only the first client is being added. I used a tutorial to help get me started. I have included my code below. When I try and add another client it doesnt appear to be added. If I add one client I get a response from the server like I want but only the first message I enter then after that it stops sending correctly.
Server Code:
int main(void)
{
struct sockaddr_in my_addr, cli_addr[10],cli_temp;
int sockfd;
socklen_t slen[10],slen_temp;
slen_temp = sizeof(cli_temp);
char buf[BUFLEN];
int clients = 0;
int client_port[10];
if ((sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP))==-1)
{
printf("test\n");
err("socket");
}else{
printf("Server : Socket() successful\n");
}
bzero(&my_addr, sizeof(my_addr));
my_addr.sin_family = AF_INET;
my_addr.sin_port = htons(PORT);
my_addr.sin_addr.s_addr = htonl(INADDR_ANY);
if (bind(sockfd, (struct sockaddr* ) &my_addr, sizeof(my_addr))==-1)
{
err("bind");
}else{
printf("Server : bind() successful\n");
}
int num_clients = 0;
while(1)
{
//receive
printf("Receiving...\n");
if (recvfrom(sockfd, buf, BUFLEN, 0, (struct sockaddr*)&cli_temp, &slen_temp)==-1)
err("recvfrom()");
if (clients <= 10) {
cli_addr[clients] = cli_temp;
client_port[clients] = ntohs(cli_addr[clients].sin_port);
clients++;
printf("Client added\n");
//printf("%d",clients);
int i;
for(i=0;sizeof(clients);i++) {
sendto(sockfd, buf, BUFLEN, 0, (struct sockaddr*)&cli_addr[i], sizeof(cli_addr[i]));
}
}
}
close(sockfd);
return 0;
}
I have included the client code as well in case it helps.
void err(char *s)
{
perror(s);
exit(1);
}
sig_atomic_t child_exit_status;
void clean_up_child_process (int signal_number)
{
/* Clean up the child process. */
int status;
wait (&status);
/* Store its exit status in a global variable. */
child_exit_status = status;
}
int main(int argc, char** argv)
{
struct sockaddr_in serv_addr;
int sockfd, slen=sizeof(serv_addr);
char buf[BUFLEN];
struct sigaction sigchld_action;
memset (&sigchld_action, 0, sizeof (sigchld_action));
sigchld_action.sa_handler = &clean_up_child_process;
sigaction (SIGCHLD, &sigchld_action, NULL);
int pid,ppid;
if(argc != 2)
{
printf("Usage : %s <Server-IP>\n",argv[0]);
exit(0);
}
if ((sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP))==-1)
err("socket");
bzero(&serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(PORT);
if (inet_aton(argv[1], &serv_addr.sin_addr)==0)
{
fprintf(stderr, "inet_aton() failed\n");
exit(1);
}
pid = fork();
if (pid<0) {
err("Fork Error");
}else if (pid==0) {
//child process will receive from server
while (1) {
bzero(buf,BUFLEN);
//printf("Attempting to READ to socket %d: ",sockfd);
fflush(stdout);
//recvfrom here
if (recvfrom(sockfd, buf, BUFLEN, 0, (struct sockaddr*)&serv_addr, &slen)==-1)
err("recvfrom()");
printf("The message from the server is: %s \n",buf);
if (strcmp(buf,"bye\n") == 0) {
ppid = getppid();
kill(ppid, SIGUSR2);
break;
}
}
}else {
//parent will send to server
while(1){
printf("Please enter the message to send: ");
bzero(buf,BUFLEN);
fgets(buf,BUFLEN,stdin);
printf("Attempting to write to socket %d: ",sockfd);
fflush(stdout);
//send to here
if (sendto(sockfd, buf, BUFLEN, 0, (struct sockaddr*)&serv_addr, slen)==-1)
{
err("sendto()");
}
}
}
close(sockfd);
return 0;
}
Several problems jump out at me. First, every time you receive a message it will consider that to be a new client. Instead of just incrementing the clients variable for a message, you'll need to scan through the array to see if the source address is already present. Second, sizeof(clients) will return a static value (probably 4) depending on how many bytes an int occupies on your machine. That loop should be for( int i = 0; i < clients; i++ ).
You also have a variable named num_clients which is not used. Is that supposed to be there for something and maybe is causing some confusion?
Finally, instead of using the magic value 10 all over the place, use #define MAX_CONNECTIONS 10 and then replace all those numbers with MAX_CONNECTIONS. It's a lot easier to read and change later.

Resources