c - How would I go about making this udpclient asynchronous using pthreads? -
how go making udpclient asynchronous using pthreads? want make sure udp datagram won't lost , don't want client program wait forever , not able send more messages
/*udpclient.c program */
#include <stdio.h> #include <stdlib.h> #include <string.h> #ifdef win #include <winsock.h> #include <windows.h> #endif #ifndef win #include <sys/types.h> #include <arpa/inet.h> #include <sys/socket.h> #endif /* here details of sockaddr_in structure , sockaddr structure these declarations copied winsock.h struct in_addr { struct holds 32 bit ip address union { struct { u_char s_b1,s_b2,s_b3,s_b4; } s_un_b; struct { u_short s_w1,s_w2; } s_un_w; u_long s_addr; } s_un; #define s_addr s_un.s_addr struct sockaddr_in { notice structure 16 bytes long short sin_family; u_short sin_port; struct in_addr sin_addr; char sin_zero[8]; }; struct sockaddr { generic address structure 16 bytes long, too! u_short sa_family; char sa_data[14]; }; */ /* have send on same port server listening on */ #define port 20009 /* simple upd client */ int main() { #ifdef win socket sock; #else int sock; #endif int size; int nbytes, flags; int i; char * cp; #ifdef win wsadata wsadata; int ncode; #endif char buffer[100]; char str_addr[20]; /* holds chars of ip address */ struct sockaddr_in target_pc, me; /* magic call initialize network i/o code - microsoft requires */ #ifdef win if((ncode = wsastartup(makeword(1,1), &wsadata)) != 0){ printf("opps! wsa error %d\n",ncode); return -1; } #endif /* create socket send on */ sock = socket(pf_inet,sock_dgram,0); if(sock < 0) { printf("socket error = %d\n", sock); return -1; } /* fill in address family , port, not know destination ip address yet */ target_pc.sin_family = pf_inet; target_pc.sin_port = htons(port); /* fill in address , port */ me.sin_family = pf_inet; me.sin_port = htons(0); me.sin_addr.s_addr = htonl(inaddr_any); = bind(sock, (struct sockaddr *) &me, sizeof(me)); if( < 0) { printf("bind result: %d\n", i); return -1; } nbytes = 99; while(1){ printf("enter target ip address: "); cp = fgets(str_addr,19,stdin); /* remove \n */ str_addr[strlen(str_addr)-1] = '\0'; /* inet_addr function converts string form of ip address 32 binary integer */ target_pc.sin_addr.s_addr = inet_addr(&str_addr[0]); printf("enter message: "); cp = fgets(buffer,99,stdin); /* string length send many characters */ nbytes = strlen(buffer); flags = 0; size = sendto(sock, (char *) buffer, nbytes,flags,(struct sockaddr *)&target_pc,sizeof(target_pc)); printf("msg size = %d size = %d\n", nbytes, size); //added int addrlen = sizeof(target_pc); size = recvfrom(sock, buffer, nbytes, flags, (struct sockaddr *)&target_pc,&addrlen); if((size > 0) && (size < 99)){ buffer[size] = '\0'; //add null byte buffer holds string = puts((char *) buffer); // write string display } } #ifdef win system("pause"); #endif return 0; }
/udpserver.c program/
#include <stdio.h> #include <stdlib.h> #include <errno.h> #ifdef win #include <winsock.h> #include <windows.h> #endif #ifndef win #include <sys/types.h> #include <arpa/inet.h> #include <sys/socket.h> #endif #define port 20009 /* simple upd server program receives short messages (<99 characters) ip address , writes them display sure use linker line option "-l wsock32" */ int main() { /* first define socket socket i/o port file descriptor */ #ifdef win socket sock; /* socket typedef structure */ #else int sock; #endif int size; int nbytes, flags; #ifdef win int addrlen; #else socklen_t addrlen; #endif int i; /* char loopback[20]="127.0.0.1"; */ #ifdef win wsadata wsadata; /* struct holds windows required data */ int ncode; #endif char buffer[100]; struct sockaddr_in server; /* holds ip address , port info */ struct sockaddr_in from; /* holds same info sender of packet received */ /* call wsastartup windows magic */ #ifdef win if((ncode = wsastartup(makeword(1,1), &wsadata)) != 0){ printf("opps! wsa error %d\n",ncode); exit; } #endif /* create socket called sock. datagram socket */ sock = socket(af_inet,sock_dgram,0); if(sock < 0){ printf("socket error = %d\n", sock); return -1; } server.sin_family = af_inet; /* initialize server address family */ server.sin_addr.s_addr = htonl(inaddr_any); /* notice struct within struct */ /* printf("%x\n",server.sin_addr.s_addr); */ server.sin_port = htons(port); /* associate socket address structure - called binding */ = bind(sock, (struct sockaddr *) &server, sizeof(server)); if( < 0) { printf("bind result: %d\n", i); return -1; } else printf("simple udp server ready!\n\n"); nbytes = 99; /* receive packets 99 bytes long */ flags = 0; /* must 0 or not work! */ while(1){ /* recvfrom function read , arguments are: sock - socket reading buffer - array read data nbytes - read many bytes flags - used special purposes - not needed here - sockaddr struct hold ip address , port of sender of packet addrlen - size of sockaddr struct written function */ addrlen = sizeof(from); size = recvfrom(sock, buffer, nbytes, flags, (struct sockaddr *)&from, &addrlen); if((size > 0) && (size < 99)){ buffer[size] = '\0'; /* add null byte buffer holds string */ = puts((char *) buffer); /* write string display */ } //echo message client if(sock < 0) {// printf("socket error = %d\n", sock);// return -1;// }// sendto(sock, buffer, nbytes, flags, (struct sockaddr *)&from,addrlen); // } #ifdef win system("pause"); #endif return 0; }
we create 2 threads: 1 sendto (that waits user input) , other recvfrom(). next, can have recvrom() use pthread condvar (by calling pthread_cond_wait() on condvar , pthread mutex) , wait. when user provides input, can sendto (which not blocking) , call pthread_cond_signal() wake other thread.
you this, if wanted. if application permits, skip pthread_cond_wait() since recvfrom() anyways blocking call. so, way, recvfrom() block go out of sync send calls. other option use main() thread sendto() thread -- in case, need 1 additional thread recv calls.
Comments
Post a Comment