I have sent message from client side and it sent successfully using sendto. But on server side I have created multiple raw sockets, to monitor event on them, used select. But event on rfds not getting noticed by select. Why so? It remains blocked on select system call.
void main()
{
int readSet[2],i;
struct sockaddr_in source;
socklen_t client_addr_size;
//Creating Socket
readSet[0]=socket(AF_INET,SOCK_RAW,221);
readSet[1]=socket(AF_INET,SOCK_RAW,222);
fd_set rfds;
struct timeval tv;
if(readSet[0]==-1 || readSet[1]==-1)
{
perror("\nSocket:");
exit(0);
}
printf("\nSocket Created\n");
memset(&source, 0, sizeof(struct sockaddr_in));
source.sin_family=AF_INET;
source.sin_addr.s_addr=inet_addr("127.0.0.1");
FD_ZERO(&rfds);
while(1)
{
for(i=0; i<2; i++)
FD_SET(readSet[i],&rfds);
printf("\nBefore select\n");
int ret = select(readSet[1]+1, &rfds, NULL, NULL, NULL);
printf("\nRetval:%d\n",ret);
if(ret>0)
{
for(i=0; i<2; i++)
{
if(FD_ISSET(readSet[i],&rfds))
{
char buff[4096];
int ds=0;
if( (ds=recvfrom(readSet[i], buff, 4096, 0, (struct sockaddr *)&source, &client_addr_size)) <0 )
perror("Error in recv: \n");
printf("\nData Receved successfully...%d\n",ds);
printIPHeader((unsigned char *)buff);
break;
}
}//For loop
}
}
sleep(1);
}
//Client siode code
void main()
{
int rsfd1=0,rsfd2;
struct sockaddr_in dest_addr;
socklen_t client_addr_size;
//Creating Socket
rsfd1=socket(AF_INET,SOCK_RAW,221);
rsfd2=socket(AF_INET,SOCK_RAW,221);
if(rsfd1==-1 || rsfd2==-1)
{
perror("\nSocket:");
exit(0);
}
printf("\nSocket Created: \n");
const int val = 1;
if(setsockopt(rsfd1, IPPROTO_IP, IP_HDRINCL, &val, sizeof(val)) < 0)
{
perror("\nsetsockopt() error:");
exit(-1);
}
if(setsockopt(rsfd2, IPPROTO_IP, IP_HDRINCL, &val, sizeof(val)) < 0)
{
perror("\nsetsockopt() error:");
exit(-1);
}
//Constructing IP Header
char buffer[4096];
memset(&buffer,0,sizeof(buffer));
char *msg="Hey there, how are you";
// Our own headers' structures
struct iphdr *iph= (struct iphdr *) buffer;
iph->version=4;
iph->ihl=5;
iph->tos=16;
iph->tot_len=htons(sizeof(iph)+sizeof(msg));
iph->id=0;
iph->ttl=255; //Number of hops
iph->protocol=253;
iph->saddr=inet_addr("127.0.0.1");
iph->daddr=inet_addr("127.0.0.1");
int iphdrlen =iph->ihl*4;
strcat(buffer+iphdrlen,msg);
//End
memset(&dest_addr, 0, sizeof(struct sockaddr_in));
dest_addr.sin_family=AF_INET;
dest_addr.sin_addr.s_addr=inet_addr("127.0.0.1");
printf("\nCustom IP Header to sent...\n");
printIPHeader((unsigned char *)buffer);
int n=0;
if( (n=sendto(rsfd1,buffer,23,0,(struct sockaddr *)&dest_addr,sizeof(dest_addr))) <0 )
perror("Sendto error: ");
char * msg1="I am fine\0";
strcat(buffer+iphdrlen,msg1);
//if( (n=sendto(rsfd2,buffer,23,0,(struct sockaddr *)&dest_addr,sizeof(dest_addr))) <0 )
//perror("Sendto error: ");
printf("\nData Sent Succefully:%d\n",n);
}
Related
Using thread, I wanted to launch UDP server on background.
But the server start and loop forever checking if any packet is received.
The same thread work fine if I use TCP server instead.
the test code is the following:
int udp_server_listen () {
printf("udp_server_listen \n");
int res;
unsigned char rsp_buf[1024];
struct sockaddr_in src;
socklen_t srclen;
memset(&src, 0, sizeof(src));
srclen = sizeof(src);
listen(s , 3);
//Accept and incoming connection
int c = sizeof(struct sockaddr_in);
int client_sock;
while( (client_sock = accept(s, (struct sockaddr *)&src, (socklen_t*)&c)) )
{
sleep(1);
printf("OK \n");
}
}
void *thread_udp_cr_listen (void *v)
{
udp_server_listen();
return NULL;
}
int s;
int main()
{
printf("start test \n");
struct sockaddr_in *local = malloc(sizeof (struct sockaddr_in *));
s = socket(AF_INET, SOCK_DGRAM, 0); // UDP
printf("create socket end\n");
int reusaddr = 1;
int reusport = 1;
if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &reusaddr, sizeof(int)) < 0)
{
printf("setsockopt(SO_REUSEADDR) failed \n");
}
if (setsockopt(s, SOL_SOCKET, SO_REUSEPORT, &reusport, sizeof(int)) < 0)
{
printf("setsockopt(SO_REUSEPORT) failed \n");
}
struct timeval tv;
tv.tv_sec = 2; /* 30 Secs Timeout */
tv.tv_usec = 0; // Not init'ing this can cause strange errors
setsockopt(s, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv,sizeof(struct timeval));
fcntl(s, F_SETFL, O_NONBLOCK);
printf(" Bind to a specific network interface and a specific local port\n");
int i = 0;
for(;i<6;i++)
{
if (bind(s, (struct sockaddr *)&local, sizeof(local)) < 0)
{
printf("bind Faild %d\n", i);
sleep(1);
continue;
}
break;
}
error = pthread_create(&udp_cr_server_thread, NULL, &thread_udp_cr_listen, NULL);
if (error<0)
{
printf("thread error \n");
}
pthread_join(udp_cr_server_thread, NULL);
}
You have one serious problem here:
struct sockaddr_in *local = malloc(sizeof (struct sockaddr_in *));
because you're just allocating the size of a pointer instead of the size of the struct itself.
This should of course be:
struct sockaddr_in *local = malloc(sizeof (struct sockaddr_in));
Two more problems with the same variable in this line:
if (bind(s, (struct sockaddr *)&local, sizeof(local)) < 0)
This should be:
if (bind(s, (struct sockaddr *)local, sizeof(*local)) < 0)
UDP server is receiving packets with the select system call. And I want to receive the latest packet from each UDP-client. (I also want to listen to multiple UDP client packets).
The codes of my simple UDP-server:
int main(void) {
int fd;
int port = 5678;
char buffer[1024];
fd_set readfs;
socklen_t client_length;
struct timeval timeout_interval;
struct sockaddr_in6 server_addr;
struct sockaddr_in6 client_addr;
int result;
int recv;
char client_addr_ipv6[100];
fd = socket(PF_INET6, SOCK_DGRAM, 0);
printf(" \e[1m \e[34m ---------------------------------------- \n-------------------- UDP SERVER --------------------\n \e[39m \e[0m \n");
printf("Process: \e[34m %d \e[49m Port ..\n", port);
if (fd < 0) {
printf("ERR: fd < 0");
} else {
memset(&server_addr, 0, sizeof(server_addr));
server_addr.sin6_family = AF_INET6;
server_addr.sin6_addr = in6addr_any;
server_addr.sin6_port = htons(port);
memset(&client_addr, 0, sizeof(client_addr));
client_addr.sin6_family = AF_INET6;
client_addr.sin6_addr = in6addr_any;
client_addr.sin6_port = htons(port);
if (bind(fd, (struct sockaddr *) &server_addr, sizeof(server_addr))
>= 0) {
printf("\e[1m INFO: \e[0m \e[34m Bind success.. \e[39m\n");
} else {
printf("Bind.");
return -1;
}
for (;;) {
FD_ZERO(&readfs);
FD_SET(fd, &readfs);
int max_fd = MAX(0, fd);
timeout_interval.tv_sec = 3;
timeout_interval.tv_usec = 50000000;
result = select(max_fd + 1, &readfs, NULL, NULL, &timeout_interval);
//printf("\n %d \t %d \n", result, fd);
if (result < 0) {
printf("ERR\n");
} else if (result == 0) {
printf("\nTimeout\n");
} else {
if (FD_ISSET(fd, &readfs)) {
client_length = sizeof(client_addr);
if ((recv = recvfrom(fd, buffer, sizeof(buffer), 0,
(struct sockaddr *) &client_addr, &client_length))
< 0) {
printf("Recv-ERR!");
break;
}
inet_ntop(AF_INET6, &(client_addr.sin6_addr), client_addr_ipv6, 100);
//printf("Client IP/Port : %s ",client_addr_ipv6);
printf("\n ------------------------------------------ \n");
printf("\e[1m Data: \e[0m \e[32m %.*s \n Client IP/Port : \e[34m %s / %d \n\e[39m", recv, buffer,client_addr_ipv6,ntohs(client_addr.sin6_port));
}
}
}
}
}
The best way to handle this is to have the sender put a sequence number in each packet. For each packet that is sent out, the sequence number increases by 1.
On the receiver side, you would keep track of the counter of the last packet you received. If the next packet that comes in has a larger counter, it's the latest. If it's not larger, it's an older packet and you can handle it in an appropriate manner for your application.
Also, you should rename you recv variable to something like recv_len. recv is the name of a socket function that would be masked by this variable definition.
I have following two files
Client.c
int main(void)
{
struct sockaddr_in si_other;
int s, i, slen=sizeof(si_other);
char buf[BUFLEN];
if ((s=socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP))==-1)
exit(-1);
memset((char *) &si_other, 0, sizeof(si_other));
si_other.sin_family = AF_INET;
si_other.sin_port = htons(PORT);
if (inet_aton(SRV_IP, &si_other.sin_addr)==0)
{
fprintf(stderr, "inet_aton() failed\n");
exit(1);
}
for (i=0; i<NPACK; i++)
{
printf("Sending packet %d\n", i);
sprintf(buf, "This is packet %d\n", i);
if (sendto(s, buf, BUFLEN, 0, &si_other, slen)==-1)
exit(1);
}
sleep(10);
close(s);
return 0;
}
Server.c
int tries=0; /* Count of times sent - GLOBAL for signal-handler access */
void diep(char *s)
{
perror(s);
exit(1);
}
void CatchAlarm(int ignored) /* Handler for SIGALRM */
{
tries += 1;
}
void DieWithError(char *errorMessage)
{}
/* Error handling function */
void *print_message_function( void *ptr )
{
char *message;
usleep(6200*1000);
message = (char *) ptr;
printf("%s \n", message);
sleep(20);
}
int main(void)
{
struct sockaddr_in si_me, si_other;
int s, i, slen=sizeof(si_other);
struct sigaction myAction; /* For setting signal handler */
const char *message1 = "Thread 1====================================";
char buf[BUFLEN];
pthread_t thread1, thread2;
pthread_create( &thread1, NULL, print_message_function, (void*) message1);
if ((s=socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP))==-1)
diep("socket");
myAction.sa_handler = CatchAlarm;
if (sigfillset(&myAction.sa_mask) < 0) /* block everything in handler */
DieWithError("sigfillset() failed");
myAction.sa_flags = 0;
if (sigaction(SIGALRM, &myAction, 0) < 0)
DieWithError("sigaction() failed for SIGALRM");
memset((char *) &si_me, 0, sizeof(si_me));
si_me.sin_family = AF_INET;
si_me.sin_port = htons(PORT);
si_me.sin_addr.s_addr = htonl(INADDR_ANY);
if (bind(s, &si_me, sizeof(si_me))==-1)
diep("bind");
alarm(TIMEOUT_SECS);
for (i=0; i<NPACK; i++) {
if (recvfrom(s, buf, BUFLEN, 0, &si_other, &slen)==-1)
{
printf("Inside eagain %d\n",errno);
if(errno == EINTR)
{
alarm(TIMEOUT_SECS); /* Set the timeout */
}
else
exit(-1);
}
else
printf("Received packet from %s:%d\nData: %s\n\n",
inet_ntoa(si_other.sin_addr), ntohs(si_other.sin_port), buf);
}
alarm(0);
pthread_join( thread1, NULL);
close(s);
return 0;
}
I am running Server first then Client. In some occurrences Server is not able to receive the message sent my client. Though client sent it successfully. Even EINTR error also I am getting because of alarm but still recvfrom function is getting blocked in between
I solved the problem. The reason is in my system the value of net.core.rmem_max was set to 12KB. And in this case I was sending MBs of data within a very short span of life. So receiver buffer was soon filled up and UDP was ignoring the rest of the buffer. I have increased the net.core.rmem_max to 10MB using following command
sysctl -w net.core.rmem_max=Value
After that this program is working fine.
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.
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.