[英]Time measure UDP socket C
I´m trying to obtain the performance in a Client (PC i7 3.4 GHz Kubuntu 15.04) - Server (RaspberryPi 700 Mhz Raspbian Jessie) architecture with sockets, measuring the spent time sending and receiving with at least microseconds precision. 我正在尝试在具有套接字的客户端(PC i7 3.4 GHz Kubuntu 15.04)-服务器(RaspberryPi 700 Mhz Raspbian Jessie)体系结构中获得性能,以至少微秒的精度测量发送和接收所花费的时间。
Concretely, I have a client (PC) that makes 100 times: 具体来说,我有一个客户端(PC),它的访问次数是100次:
and a server (RaspberryPi) that makes 100 times: 和一台服务器(RaspberryPi),其性能是100倍:
I´m measuring time before send and after receive in client and subtracting it the time taken in server to receive and send, so the total time would be: Tt=TT' but sometimes I get negative measures... :S 我正在测量客户端发送之前和接收之后的时间,然后减去服务器接收和发送服务器所花费的时间,因此总时间为:Tt = TT',但有时我会得到负面的衡量标准...:S
I´m measuring with this macro, where in 'X' I placed my code (C:sendto()-recvfrom() or S:recvfrom()-sendto()): 我正在用此宏进行测量,在“ X”中放置了我的代码(C:sendto()-recvfrom()或S:recvfrom()-sendto()):
float timef=0.0;
#define TIME_MEASURE(X) \
{ \
struct timespec ts1, ts2; \
clock_gettime( CLOCK_REALTIME, &ts1 ); \
X; \
clock_gettime( CLOCK_REALTIME, &ts2 ); \
timef=(float) ( 1.0*(1.0*ts2.tv_nsec - ts1.tv_nsec*1.0)*1e-9 \
+ 1.0*ts2.tv_sec - 1.0*ts1.tv_sec ) ); \
}
//Client pseudo-code example
main(){
TIME_MEASURE(
while(i<100)
{
sendto(...);
recvfrom(..);
}
);
}
I have to measure time in any case, so another solution to obtain performance is not valid for me. 无论如何,我都必须测量时间,因此获取性能的另一种解决方案对我而言无效。
Can anyone suggest what can I do to solve this problem? 谁能建议我该怎么解决这个问题?
Than you so much. 比你好
(V2. EDITED WITH 'int64_t' and 'double' VALUES) (V2。使用“ int64_t”和“ double”值编辑)
Here is my full code. 这是我的完整代码。
It can be downloaded from: 可以从以下位置下载:
V1 - https://www.dropbox.com/sh/gb4mhn3amkyqhc1/AAC6FxKCfDxXQYgzRsjArvXQa?dl=0 V1- https: //www.dropbox.com/sh/gb4mhn3amkyqhc1/AAC6FxKCfDxXQYgzRsjArvXQa ? dl =0
V2 - https://www.dropbox.com/sh/byipa75qruc71gj/AAD2ExMlnQSaUk_Pbc5xR2lZa?dl=0 V2- https: //www.dropbox.com/sh/byipa75qruc71gj/AAD2ExMlnQSaUk_Pbc5xR2lZa ? dl =0
server.c: server.c:
/****************************************
* Servidor UDP. Recibe como argumento
* en linea de comandos el numero de puerto. El servidor
* se ejecuta en bucle
***************************************/
#include <sys/types.h>
#include <netdb.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <pthread.h>
#define TAMANO 256
#include <sys/time.h>
#include <math.h>
#include <time.h>
void * ack();
void error_fatal(char *); /* Imprime un mensaje de error y sale del programa */
int sock, length, fromlen, n, i, j, port ;
struct sockaddr_in server;
struct sockaddr_in from;
char buffer[TAMANO];
float timeArr;
float timeVector[101];
double timed;
#define TIME_MEASURE(X) \
{ \
struct timespec ts1, ts2, diff; \
clock_gettime( CLOCK_REALTIME, &ts1 ); \
X; \
clock_gettime( CLOCK_REALTIME, &ts2 ); \
timeArr= (float) ( 1.0*(1.0*ts2.tv_nsec - ts1.tv_nsec*1.0)*1e-9 \
+ 1.0*ts2.tv_sec - 1.0*ts1.tv_sec ); \
diff.tv_sec = ts2.tv_sec - ts1.tv_sec; \
diff.tv_nsec = ts2.tv_nsec - ts1.tv_nsec; \
if( diff.tv_nsec < 0 ) { \
diff.tv_sec--; \
diff.tv_nsec += 1000000000LL; \
} \
printf( "Elapsed: %u.%09lld secs\n", diff.tv_sec, diff.tv_nsec );\
const int64_t NANO = 1000000000LL; \
int64_t nsec = (int64_t)(ts2.tv_sec - ts1.tv_sec) * NANO; \
nsec += (int64_t)(ts2.tv_nsec - ts1.tv_nsec); \
printf( "Elapsed nsec: %lld.%09lld secs\n", nsec / NANO, nsec % NANO );\
timed = (double)nsec * 1e-9; \
printf("nsec=%ld\n"); \
}\
int main(int argc, char *argv[])
{
timeArr=0.1;
i=0;
pthread_t recv;
FILE *f;
if (argc < 2)
{
fprintf(stderr, "ERROR, no se ha indicado el puerto \n");
exit(1);
}
/* obtain port number */
if (sscanf(argv[1], "%d", &port) <= 0)
{
fprintf(stderr, "%s: error: wrong parameter: port\n", argv[0]);
return -2;
}
/* (1) creacion del socket del servidor*/
sock=socket(AF_INET, SOCK_DGRAM, 0);
if (sock < 0)
error_fatal("Creando el socket");
length = sizeof(server);
memset(&server,0,length); /*limpio la direccion del socket del servidor*/
/* (2) vinculo la direccion IP y puerto local al socket creado anteriormente */
server.sin_family=AF_INET;
server.sin_addr.s_addr=INADDR_ANY;
server.sin_port=htons(port);
if (bind(sock,(struct sockaddr *)&server,length)<0)
error_fatal("binding");
fromlen = sizeof(struct sockaddr_in);
/* (3) bucle principal. Pongo a recibir y responder mensajes a traves del socket*/
printf("Servidor listo y esperando tramas UDP en el puerto %d...\n", port);
while (1)
{
//el cliente manda una trama de prueba para no contar el tiempo de espera en el servidor
//client sends init frame and it is not counted
if(i==0)
{
//Recibo paquete de prueba para empezar a contar, desecho este tiempo
n = recvfrom(sock,buffer,TAMANO,0,(struct sockaddr *)&from,&fromlen);
pthread_create (&recv, NULL,ack, &fromlen);
i++;
}
else
{
TIME_MEASURE(
n = recvfrom(sock,buffer,TAMANO,0,(struct sockaddr *)&from,&fromlen);
if (n < 0)
error_fatal("recvfrom");
/*datagrama recibido*/
pthread_create (&recv, NULL,ack, &fromlen);
);
timeVector[i]=(float)timeArr;
printf("timevector[%d] = %f\n", i, timeArr);
if(i==100)
{
f=fopen("dataserver.txt", "w+");
printf("Se han recibido 100 tramas UDP\n\n\n");
for(j=0;j<=100;j++)
{
fprintf(f,"%f\n",timeVector[j]);
//printf("valores: %f\n",timeVector[j]);
}
i=0;
fclose(f);
memset(timeVector,0,100);
}
else
{
i++;
}
}
}
return 0;
}
void *ack(void *ptr){
int *fl;
fl= (int *)ptr;
buffer[n]='\0'; /* para poder imprimirlo con prinft*/
//printf("Recibido en el servidor: %s\n", buffer);
/*enviar respuesta*/
float t;
t=(float)timeArr;
//It is like an ACK, now I am not using this value
n = sendto(sock,&t,sizeof(float),0,(struct sockaddr *)&from,fromlen);
memset(buffer,0,TAMANO);
if (n < 0)
error_fatal("sendto");
pthread_exit(NULL);
}
void error_fatal(char *msg)
{
perror(msg);
exit(1);
}
client.c client.c
/*******************************************************************
* Cliente de eco remoto sobre UDP:
*
* cliente dir_ip_maquina puerto
********************************************************************/
#include <sys/types.h>
#include <netdb.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#define TAMANO 256 /* tamano del buffer de recepcion */
#include <sys/time.h>
#include <math.h>
#include <time.h>
void error_fatal(char *); /* Imprime un mensaje de error y sale del programa */
float timeArr;
float timeVector[101];
int i;
double timed;
#define TIME_MEASURE(X) \
{ \
struct timespec ts1, ts2, diff; \
clock_gettime( CLOCK_REALTIME, &ts1 ); \
X; \
clock_gettime( CLOCK_REALTIME, &ts2 ); \
timeArr= (float) ( 1.0*(1.0*ts2.tv_nsec - ts1.tv_nsec*1.0)*1e-9 \
+ 1.0*ts2.tv_sec - 1.0*ts1.tv_sec ); \
diff.tv_sec = ts2.tv_sec - ts1.tv_sec; \
diff.tv_nsec = ts2.tv_nsec - ts1.tv_nsec; \
if( diff.tv_nsec < 0 ) { \
diff.tv_sec--; \
diff.tv_nsec += 1000000000LL; \
} \
printf( "Elapsed: %u.%09lld secs\n", diff.tv_sec, diff.tv_nsec );\
const int64_t NANO = 1000000000LL; \
int64_t nsec = (int64_t)(ts2.tv_sec - ts1.tv_sec) * NANO; \
nsec += (int64_t)(ts2.tv_nsec - ts1.tv_nsec); \
printf( "Elapsed nsec: %lld.%09lld secs\n", nsec / NANO, nsec % NANO );\
timed = (double)nsec * 1e-9; \
printf("nsec=%ld\n"); \
}\
/*
*
* const int64_t NANO = 1000000000LL; \
int64_t nsec = (int64_t)(ts2.tv_sec - ts1.tv_sec) * NANO; \
nsec += (int64_t)(ts2.tv_nsec - ts1.tv_nsec); \
printf( "Elapsed: %lld.%09lld secs\n", nsec / NANO, nsec % NANO );\
\
*/
int main(int argc, char *argv[])
{
int sock; /* descriptor del socket del cliente */
int length, n, j, port;
struct sockaddr_in server, from; /* direcciones del socket del servidor y cliente */
struct hostent *hp; /* estructura para el nombre del servidor (ver gethostbyname) */
char buffer[TAMANO]; /* buffer de recepcion y envio del mensaje */
char buffercpy[TAMANO];
float bufferf[7];
FILE *f = fopen("data.txt", "w+");
struct timespec spec;
clockid_t clk_id;
clk_id=CLOCK_REALTIME;
i=0;
if (argc != 3)
{
fprintf(stderr,"Uso: ./client server port\n");
exit(1);
}
/* obtain port number */
if (sscanf(argv[2], "%d", &port) <= 0)
{
fprintf(stderr, "%s: error: wrong parameter: port\n", argv[0]);
return -2;
}
printf("El cliente va a mandar por el puerto %d\n", port);
/* (1) creacion del socket UDP del cliente */
sock= socket(AF_INET, SOCK_DGRAM, 0);
if (sock < 0)
error_fatal("socket");
server.sin_family = AF_INET; /*dominio de Internet*/
/* (2) averigua la direccion IP a partir del nombre del servidor*/
hp = gethostbyname(argv[1]);
if (hp==0)
error_fatal("Host desconocido");
/* (3) copia la IP resuelta anteriormente en la direccion del socket del servidor */
memcpy((char *)&server.sin_addr,(char *)hp->h_addr,hp->h_length);
if ( clock_getres( clk_id, &spec) == -1 )
{
perror( "clock get resolution" );
return EXIT_FAILURE;
}
//printf ("CLOCK_REALTIME: %ld s, %ld ns\n", spec.tv_sec,spec.tv_nsec);
/* (4) copia el puerto destino en la direccion del socket del servidor */
server.sin_port = htons(port);
length=sizeof(struct sockaddr_in);
printf("Por favor, introduce el mensaje: ");
memset(buffer,0,TAMANO); /*limpio el buffer*/
fgets(buffer,TAMANO-1,stdin);
strcpy(buffercpy, buffer);//Copio el mensaje a un nuevo buffer para que se repita en el while
while(i<=100)
{
//client sends init frame and it is not counted
if(i==0)
{
/* (5) envia al socket del servidor el mensaje almacenado en el buffer*/
n=sendto(sock,buffer,strlen(buffer),0,(struct sockaddr *) &server,length);
if (n < 0)
error_fatal("Sendto");
/* (6) lee del socket el mensaje de respuesta del servidor*/
n = recvfrom(sock,bufferf,sizeof(float),0,(struct sockaddr *) &from, &length);
if (n < 0)
error_fatal("recvfrom");
i++;
}
else
{
TIME_MEASURE(
memset(buffer, '\0', sizeof(buffer));
strcpy(buffer, buffercpy);
/* (5) envia al socket del servidor el mensaje almacenado en el buffer*/
n=sendto(sock,buffer,strlen(buffer),0,(struct sockaddr *) &server,length);
if (n < 0)
error_fatal("Sendto");
/* (6) lee del socket el mensaje de respuesta del servidor*/
n = recvfrom(sock,bufferf,sizeof(float),0,(struct sockaddr *) &from, &length);
if (n < 0)
error_fatal("recvfrom");
);
timeVector[i]=(float)timeArr;
printf("Tiempo de procesamiento cliente - timeVector [%d]: %f\n", i,timeArr);
//timeVector[i]+=(float)(0.0 - *bufferf);
//printf("timeVector negativo[%d]= %f\n", i, timeVector[i]);
buffer[n]='\0'; /* para poder imprimirlo con printf*/
bufferf[n]='\0'; /* para poder imprimirlo con printf*/
//printf("Recibido en el cliente: %f ACK(%d)%c\n",*bufferf,i,'\0');
printf("timeVector TOTAL= %f\n\n", timeVector[i]);
//printf("buffer=%s%c\n",buffer,'\0');
if(i==100){
for(j=1;j<=100;j++){
fprintf(f,"%f\n",timeVector[j]);
//printf("valores: %f\n",timeVector[j]);
}
printf("Se han enviado 100 tramas UDP \n\n\n");
}
i++;
}
}
fclose(f);
/*cerramos el socket*/
if(close(sock) < 0)
error_fatal("close");
}
void error_fatal(char *msg)
{
perror(msg);
exit(1);
}
I get warnings in number formats, so I think that it is probably that printed values wouldn't be correct. 我收到数字格式的警告,因此我认为打印的值可能不正确。
These are warnings which I get: 这些是我得到的警告:
server.c: In function ‘main’:
server.c:50:18: warning: format ‘%u’ expects argument of type ‘unsigned int’, but argument 2 has type ‘__time_t {aka long int}’ [-Wformat=]
printf( "Elapsed: %u.%09lld secs\n", diff.tv_sec, diff.tv_nsec );\
^
server.c:122:13: note: in expansion of macro ‘TIME_MEASURE’
TIME_MEASURE(
^
server.c:50:18: warning: format ‘%lld’ expects argument of type ‘long long int’, but argument 3 has type ‘__syscall_slong_t {aka long int}’ [-Wformat=]
printf( "Elapsed: %u.%09lld secs\n", diff.tv_sec, diff.tv_nsec );\
^
server.c:122:13: note: in expansion of macro ‘TIME_MEASURE’
TIME_MEASURE(
^
server.c:54:18: warning: format ‘%lld’ expects argument of type ‘long long int’, but argument 2 has type ‘long int’ [-Wformat=]
printf( "Elapsed nsec: %lld.%09lld secs\n", nsec / NANO, nsec % NANO )
^
server.c:122:13: note: in expansion of macro ‘TIME_MEASURE’
TIME_MEASURE(
^
server.c:54:18: warning: format ‘%lld’ expects argument of type ‘long long int’, but argument 3 has type ‘long int’ [-Wformat=]
printf( "Elapsed nsec: %lld.%09lld secs\n", nsec / NANO, nsec % NANO )
^
server.c:122:13: note: in expansion of macro ‘TIME_MEASURE’
TIME_MEASURE(
^
server.c:56:17: warning: format ‘%ld’ expects a matching ‘long int’ argument [-Wformat=]
printf("nsec=%ld\n"); \
^
server.c:122:13: note: in expansion of macro ‘TIME_MEASURE’
TIME_MEASURE(
^
You might be getting problems with converting these numbers to floating point. 将这些数字转换为浮点数时可能会遇到问题。 Try computing the difference into a suitably large integer datatype.
尝试将差异计算为适当的大整数数据类型。 At least to begin with, and then work back from there.
至少要从头开始,然后再从那里开始。
const int64_t NANO = 1000000000LL;
int64_t nsec = (int64_t)(ts2.tv_sec - ts1.tv_sec) * NANO;
nsec += (int64_t)(ts2.tv_nsec - ts1.tv_nsec);
printf( "Elapsed: %lld.%09lld secs\n", nsec / NANO, nsec % NANO );
If you wanted a float out of that, beware that single-precision is pretty limited. 如果您想从中浮出水面,请注意单精度非常有限。 You may be able to clamp it to microseconds, but for longer intervals you might not get microsecond resolution.
您可能可以将其钳制到微秒,但是对于较长的时间间隔,您可能无法获得微秒的分辨率。
timef = (float)(nsec / 1000LL) * 1e-6f;
Better to use double: 最好使用double:
double timef;
timef = (double)nsec * 1e-9;
Of course, you could just use a timespec itself: 当然,您可以只使用timespec本身:
struct timespec diff;
diff.tv_sec = ts2.tv_sec - ts1.tv_sec;
diff.tv_nsec = ts2.tv_nsec - ts1.tv_nsec;
if( diff.tv_nsec < 0 ) {
diff.tv_sec--;
diff.tv_nsec += 1000000000LL;
}
printf( "Elapsed: %u.%09lld secs\n", diff.tv_sec, diff.tv_nsec );
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.