LQ Newbie
Registered: Apr 2010
Location: hangzhou, china
Distribution: Fedora 13
Posts: 9
Rep:
|
Code analysis: Why Receiver have to wait for 2s?
Hi,
When I'm learning programing of UDP communication on Linux, I found a problem which I could not explain.
Here is what I'm meant to do:
1) Setup UDP listener in main thread and print out what it got;
2) Create a timer in main thread and also set a TimerExpiration Callback to send Pkt periodicially.
The problem is that after Callback send out the Pkt Receiver have to wait for 2s, which is also the interval for the timer, to get the data. But I think there should be not the delay between TX&RX. Could you help tell me why? Thanks!
Here is log:
# ./a.out
Timer is created successfully!
Timer is armed successfully!
[6143832.567283768]Thread_3087104912_Sent 6 bytes to 127.0.0.1
[6143832.567353744]Thread_3087107776_Received pkt from peer: 127.0.0.1
Msg content: 0x34 0x12 0x78 0x56 0x21 0x90
[6143834.567262533]Thread_3087107776_Received pkt from peer: 127.0.0.1
Msg content: 0x34 0x12 0x78 0x56 0x21 0x90
[6143834.567345105]Thread_3087104912_Sent 6 bytes to 127.0.0.1
[6143836.567255395]Thread_3087107776_Received pkt from peer: 127.0.0.1
Msg content: 0x34 0x12 0x78 0x56 0x21 0x90
[6143836.567337518]Thread_3087104912_Sent 6 bytes to 127.0.0.1
[6143838.567255424]Thread_3087107776_Received pkt from peer: 127.0.0.1
Msg content: 0x34 0x12 0x78 0x56 0x21 0x90
[6143838.567337250]Thread_3087104912_Sent 6 bytes to 127.0.0.1
Code is here: (gcc UDP_server_client.c -Wall -lrt)
#include <stdio.h>
#include <string.h>
#include <signal.h>
#include <ctype.h>
#include <stdlib.h>
#include <time.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#include <pthread.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/wait.h>
#define UDP_SERVER_PORT 60000
#define BUF_DEPTH 200
timer_t timer_id;
char* show_msg_content(char *ptr, unsigned short len)
{
static char buf[100];
int rtn=0;
int char_printed=0;
int i=0;
for (i=0; i<len; i++)
{
rtn = snprintf(&buf[char_printed], (sizeof(buf)-char_printed), "0x%X ", *((unsigned char *)(ptr+i)));
if (rtn < 0)
{
printf("buf overflow! \n");
return NULL;
}
else
{
char_printed += rtn;
}
}
return buf;
}
void send_pkt(union sigval val)
{
int result;
static short msg[]={0x1234, 0x5678, 0x9021};
int sending_sockfd; /* file descriptor of the sending socket */
struct sockaddr_in peer_addr; /* connector's address information */
int numbytes;
sending_sockfd = socket(AF_INET, SOCK_DGRAM, 0);
if (-1 == result)
{
printf ("Failed to create Sender socket, err_no %d\n", errno);
return;
}
/* sending_sockfd not initialized, which means sys will choose one port to send pkt? */
peer_addr.sin_family = AF_INET; /* Host byte order */
peer_addr.sin_port = htons(UDP_SERVER_PORT); /* Short, network byte order */
peer_addr.sin_addr.s_addr = inet_addr("127.0.0.1"); /* Set to local ip addr */
bzero(&(peer_addr.sin_zero), 8); /* Zero the rest of the struct */
numbytes = sendto(sending_sockfd, (unsigned char *)msg, sizeof(msg), 0, (struct sockaddr *)&peer_addr, sizeof(struct sockaddr));
if (numbytes>0)
{
struct timespec tp;
clock_gettime(CLOCK_MONOTONIC, &tp);
printf("\n[%d.%ld]Thread_%lu_Sent %d bytes to %s\n", (unsigned int)(tp.tv_sec), tp.tv_nsec, (unsigned long int)(pthread_self()), numbytes, inet_ntoa(peer_addr. sin_addr )) ;
}
close ( sending_sockfd ) ;
}
int main ()
{
int result=0;
struct sigevent sig_en;
/* Setup a timer and arm it */
memset((char *)&sig_en, 0, sizeof (sig_en));
sig_en.sigev_notify = SIGEV_THREAD;
sig_en.sigev_notify_function = &send_pkt;
result = timer_create(CLOCK_MONOTONIC, &sig_en, &timer_id);
if (0 == result)
{
printf("Timer is created successfully!\n");
}
else
{
printf("Timer failed to be created!\n");
}
struct itimerspec new_value, old_value;
/* Initial expiration */
new_value.it_value.tv_sec = 2;
new_value.it_value.tv_nsec = 0;
/* each time an armed timer expires, the timer is reloaded from the value specified in new_value->it_interval */
new_value.it_interval.tv_sec = new_value.it_value.tv_sec;
new_value.it_interval.tv_nsec = new_value.it_value.tv_nsec;
result = timer_settime(timer_id, 0, &new_value, &old_value);
if (0 == result)
{
printf("Timer is armed successfully!\n");
}
else
{
printf("Timer failed to be armed!\n");
}
/* Setup UDP server */
int recv_sockfd; /* Receiver's sockfd */
struct sockaddr_in my_addr; /* My address information */
struct sockaddr_in peer_addr; /* Peer's address information */
unsigned int addr_len;
int numbytes;
char recv_buf[BUF_DEPTH];
/* Create UDP IPV4 socket */
recv_sockfd = socket(AF_INET, SOCK_DGRAM, 0);
if (-1 == recv_sockfd)
{
printf ("Failed to create Receiver socket, err_no %d\n", errno);
return -1;
}
/* Init my_addr */
my_addr.sin_family = AF_INET; /* IPV4, host byte order */
my_addr.sin_port = htons(UDP_SERVER_PORT); /* Short, network byte order */
my_addr.sin_addr.s_addr = INADDR_ANY; /* Auto-fill with my IP */
bzero(&(my_addr.sin_zero), 8); /* Zero the rest of the struct */
/* Bind socket with the UDP port */
result = bind(recv_sockfd, (struct sockaddr *)&my_addr, sizeof(struct sockaddr));
if (-1 == result)
{
printf ("Failed to bind socket, err_no %d\n", errno);
return -1;
}
/* Receive packet from peer */
addr_len = sizeof(struct sockaddr);
while (1)
{
numbytes = recvfrom(recv_sockfd, recv_buf, BUF_DEPTH, 0, (struct sockaddr *)&peer_addr, &addr_len);
if (numbytes >0)
{
struct timespec tp;
clock_gettime(CLOCK_MONOTONIC, &tp);
printf("[%d.%ld]Thread_%lu_Received pkt from peer: %s\n", (unsigned int)(tp.tv_sec), tp.tv_nsec, (unsigned long int)(pthread_self()), inet_ntoa(peer_addr.sin_addr));
printf("Msg content: %s\n", show_msg_content(recv_buf, numbytes));
}
else
{
printf("Error when recvfrom, err_no %d\n", errno);
}
}
return 0;
}
|