Hi,
I have a UDP server and client program, and they must run within a program, so I decided two threads, one for UDP server and another for UDP client.
The simple architecture is shown in attachment.
However, I can't send the packets out on the UDP client, no any time message and sigaction is triggered. Is any sigmask needs? If it is, then where should I put the mask?
The following are the source codes
The UDP server
Code:
static void SIGIOHandler( int signalType ) {
struct sockaddr_in clntAddr;
unsigned int clntLen;
int recvMsgSize;
UINT8 buf[ MSG_SIZE ];
do {
clntLen = sizeof( clntAddr );
if ( ( recvMsgSize = recvfrom( srvSock, buf, MSG_SIZE, 0, ( struct sockaddr* )&clntAddr,&clntLen ) ) < 0 ) {
if ( errno != EWOULDBLOCK ) {
...Error handler
}
} else {
printf( "Handling client %s\n", inet_ntoa( clntAddr.sin_addr ) );
if ( Sendto( srvSock, buf, recvMsgSize, 0, ( struct sockaddr* )&clntAddr, sizeof( clntAddr ),
__FILE__, __LINE__ ) != recvMsgSize ) {
...Error handler
}
}
} while ( recvMsgSize >= 0 );
printf( "%s completed\n", inet_ntoa( clntAddr.sin_addr ) );
}
void Server_Constructor () {
char buf[ 128 ];
struct sockaddr_in echoServAddr;
struct sigaction handler;
/* Initiating socket. */
srvSock = socket( PF_INET, SOCK_DGRAM, IPPROTO_UDP );
memset( &echoServAddr, 0, sizeof( echoServAddr ) );
echoServAddr.sin_family = AF_INET;
echoServAddr.sin_addr.s_addr = htonl( INADDR_ANY );
echoServAddr.sin_port = htons( ( unsigned short )23456 );
Bind( srvSock, ( struct sockaddr* )&echoServAddr, sizeof( echoServAddr ) );
/* Initiating signal handler. */
handler.sa_handler = SIGIOHandler;
if ( sigfillset( &handler.sa_mask ) < 0 ) {
...Error handler
}
handler.sa_flags = 0; /* No flags */
if ( sigaction( SIGIO, &handler, 0 ) < 0 ) {
...Error handler
}
if ( fcntl( srvSock, F_SETOWN, getpid() ) < 0 ) {
...Error handler
}
if ( fcntl ( srvSock, F_SETFL, O_NONBLOCK | FASYNC ) < 0 ) {
...Error handler
}
/* Wait forever. */
....
}
The UDP client
Code:
static void CatchAlarm ( int ignored ) {
tries += 1;
}
void Client_Sendto ( const struct sockaddr* dest_addr, const void* message ) {
int sock; /* Socket descriptor */
struct sockaddr_in echoServAddr; /* Echo server address */
struct sockaddr_in fromAddr; /* Source address of echo */
unsigned int fromSize; /* In-out of address size for recvfrom() */
struct sigaction myAction; /* For setting signal handler */
char *servIP; /* IP address of server */
char echoString[ MSG_SIZE ] = "123"; /* String to send to echo server */
char recvbuf[ MSG_SIZE ];
int respStringLen; /* Size of received datagram */
servIP = "127.0.0.1"; /* First arg: server IP address (dotted quad) */
sock = Socket( PF_INET, SOCK_DGRAM, IPPROTO_UDP, __FILE__, __LINE__ );
/* Set signal handler for alarm signal */
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");
/* Construct the server address structure */
memset(&echoServAddr, 0, sizeof(echoServAddr)); /* Zero out structure */
echoServAddr.sin_family = AF_INET;
echoServAddr.sin_addr.s_addr = inet_addr(servIP); /* Server IP address */
echoServAddr.sin_port = htons( ( unsigned short )UDP_PORT ); /* Server port */
The UDP client unable send packet out, I think it can't receive the signal in the thread, so how to do that?
/* Send the string to the server */
if (sendto(sock, echoString, MSG_SIZE, 0, (struct sockaddr *)
&echoServAddr, sizeof(echoServAddr)) != MSG_SIZE)
DieWithError("sendto() sent a different number of bytes than expected");
/* Get a response */
fromSize = sizeof( fromAddr );
alarm( TIMEOUT_SECS ); /* Set the timeout */
while ((respStringLen = recvfrom(sock, recvbuf, MSG_SIZE, 0,
(struct sockaddr *) &fromAddr, &fromSize)) < 0)
if (errno == EINTR) /* Alarm went off */
{
if (tries < MAXTRIES) /* incremented by signal handler */
{
printf("timed out, %d more tries...\n", MAXTRIES-tries);
if (sendto(sock, echoString, MSG_SIZE, 0, (struct sockaddr *)
&echoServAddr, sizeof(echoServAddr)) != MSG_SIZE)
DieWithError("sendto() failed");
alarm(TIMEOUT_SECS);
}
else
DieWithError("No Response");
}
else
DieWithError("recvfrom() failed");
alarm( 0 ); /* Cancel the timeout. */
Close( sock, __FILE__, __LINE__ );
printf( "Received: %s\n", recvbuf ); /* Print the received data */
}
static void* SENDER ( void* null ) {
do {
Client_Sendto( NULL, NULL );
sleep( 1 );
} while ( 1 );
return NULL;
}
void Client_DebugThread () {
pthread_t tid; /* Thread ID. */
pthread_attr_t rx; /* Parameter of thread. */
pthread_attr_init( &rx ); /* Free resources immediately if a thread is terminated. */
pthread_attr_setdetachstate( &rx, PTHREAD_CREATE_DETACHED );
pthread_create( &tid, &rx, SENDER, NULL, __FILE__, __LINE__ );
}