Problem bei Socketprogrammierung auf Raspberry Pi



  • Hallo Leute,

    im Rahmen einem Projektes mit einer Speicherprogrammierter Steuerung soll auf einem Raspberry Pi ein C-Anwendung laufen welche periodisch Daten aus der SPS via Ethernet herauszieht.

    Folgender Code existiert:

    #include <errno.h>
    #include <stdio.h>
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <signal.h>
    
    #define FINS_UDP_PORT 9600
    #define SERV_IP_ADDR "192.168.1.10" /*Ethernet Unit IP ADDRESS */
    #define MAX_MSG 2010
    #define RESP_TIMEOUT 2
    
    /*
    * FINS COMMUNICATIONS SAMPLE PROGRAM
    */
    
    main(argc,argv) 
    int argc;
    char *argv[];
    {
    
    	int sockfd;
    	struct sockaddr_in , ws_addr,cv_addr;
    	char fins_cmnd[MAX_MSG],fins_resp[MAX_MSG];	
    	int sendlen,recvlen,addrlen;
    	char sid=0;
    	extern recv_fail();
    
    	/* GENERATE UDP SOCKET */
    	if((sockfd=socket(AF_INET,SOCK_DGRAM,0))<0) {
    		err_exit("can’t open datagram socket");
    	}
    
    	/* ALLOCATE IP ADDRESS AND PORT# TO SOCKET */
    	bzero((char*)&ws_addr,sizeof(ws_addr));
    	ws_addr.sin_family=AF_INET;
    	ws_addr.sin_addr.s_addr=htonl(INADDR_ANY);
    	ws_addr.sin_port=htons(FINS_UDP_PORT);
    	if(bind(sockfd,(struct sockaddr*)&ws_addr,sizeof(ws_addr))<0) {
    		err_exit("cant bind local address");
    	}
    
    	/*
    	* GENERATE MEMORY AREA READ COMMAND
    	* (READ 150 WORDS FROM D00100.)
    	*/
    
    	fins_cmnd[0]=0x80; /*ICF*/
    	fins_cmnd[1]=0x00; /*RSV*/
    	fins_cmnd[2]=0x02; /*GCT*/
    	fins_cmnd[3]=0x01; /*DNA*/
    	fins_cmnd[4]=0x11; /*DA1*/ /*Ethernet Unit FINS NODE NUMBER*/
    	fins_cmnd[5]=0x00; /*DA2*/
    	fins_cmnd[6]=0x01; /*SNA*/
    	fins_cmnd[7]=0x0B; /*SA1*/ /* WS FINS NODE NUMBER */
    	fins_cmnd[8]=0x00; /*SA2*/
    	fins_cmnd[9]=++sid; /*SID*/
    	fins_cmnd[10]=0x01; /*MRC*/
    	fins_cmnd[11]=0x01; /*SRC*/
    	fins_cmnd[12]=0x82; /*VARIABLE TYPE: DM*/
    	fins_cmnd[13]=0x00; /*READ START ADDRESS: 100*/
    	fins_cmnd[14]=0x64;
    	fins_cmnd[15]=0x00;
    	fins_cmnd[16]=0x00; /*WORDS READ: 150*/
    	fins_cmnd[17]=0x96;
    
    	/*SEND FINS COMMAND*/
    
    	bzero((char*)&cv_addr,sizeof(cv_addr));
    	cv_addr.sin_family=AF_INET;
    	cv_addr.sin_addr.s_addr=inet_addr(SERV_IP_ADDR);
    	cv_addr.sin_port=htons(FINS_UDP_PORT);
    
    	singnal((SIGALRM,recv_fail);
    
    CMND_SEND:
    	sendlen = 18;
    	if(sendto(sockfd,fins_cmnd,sendlen,0,&cv_addr,sizeof(cv_addr))==sendlen){
    		alarm(RESP_TIMEOUT); /*START RESPONSE MONITOR TIMER*/
    		printf("send length %d\n",sendlen);
    	}
    	else { 
    		err_exit("send error");
    	}
    
    	/*RECEIVE FINS RESPONSE*/
    
    	if((recvlen = recvfrom(sockfd,fins_resp,MAX_MSG,0,&cv_addr,&addrlen))<0) {
    		if(errno == EINTR) {
    			goto CMND_SEND; /*RE-SEND FINS COMMAND*/
    		}
    		err_exit("receive error");
    	}
    	else {
    		alarm(0); /*STOP RESPONSE MONITOR TIMER*/
    		printf("recv length %d \n",recvlen);
    		if(recvlen<14) { /*ILLEGAL RESPONSE LENGTH CHECK*/
    			err_exit("FINS length error");
    		}
    		if((fins_cmnd[3]!=fins_resp[6])||(fins_cmnd[4]!=fins_resp[7])||(fins_cmnd[5]!=fins_resp[8])) { /*DESTINATION ADDRESS CHECK*/
    			err_exit("illegal source address error");
    		}
    		if(fins_cmnd[9]!=fins_resp[9]) { /*SID CHECK*/
    			err_exit("illegal SID error");
    		}
    	}
    
    	/*CLOSE SOCKET*/
    	close(sockfd);
    }
    
    /*
    *ERROR PROCESSING FUNCTIONS
    */
    err_exit(err_msg)
    char *err_msg;
    {
    	printf(”client: %s %x \n”,err_msg,errno);
    	exit(1);
    }
    
    /*
    *SIGNAL CAPTURE FUNCTIONS
    */
    recv_fail()
    {
    	printf("response timeout error \n");
    }
    

    Beim Kompilieren auf dem Raspberry kommen folgende Meldungen:

    pi@raspberrypi ~ $ gcc readdata.c
    readdata.c: In function ‘main’:
    readdata.c:24:21: error: expected identifier or ‘(’ before ‘,’ token
    readdata.c:36:2: warning: incompatible implicit declaration of built-in function ‘bzero’ [enabled by default]
    readdata.c:36:16: error: ‘ws_addr’ undeclared (first use in this function)
    readdata.c:36:16: note: each undeclared identifier is reported only once for each function it appears in
    readdata.c:70:16: error: ‘cv_addr’ undeclared (first use in this function)
    readdata.c:75:29: error: expected ‘)’ before ‘;’ token
    readdata.c:111:1: error: expected ‘;’ before ‘}’ token
    readdata.c: In function ‘err_exit’:
    readdata.c:119:2: error: stray ‘\224’ in program
    readdata.c:119:10: error: ‘client’ undeclared (first use in this function)
    readdata.c:119:16: error: expected ‘)’ before ‘:’ token
    readdata.c:119:16: error: stray ‘\’ in program
    readdata.c:119:16: error: stray ‘\224’ in program
    readdata.c:120:2: warning: incompatible implicit declaration of built-in function ‘exit’ [enabled by default]

    Kann jemand weiterhelfen?



  • In Zeile 24 steht ein Komma hinter struct sockaddr_in.



  • EINTR bedeutet hier, dass der Systemaufruf recvfrom unterbrochen wurde. Die Daten wurden aber dennoch gesendet. Daher solltest Du nur den Systemaufruf wiederholen und nicht das Senden. Da hast Du es auch leichter dieses (würg) goto zu entfernen.



  • Mittels google konnte ich mühselig das ganze auf eine Fehlermeldung reduzieren:

    readdata.c: In function ‘main’:
    readdata.c:77:2: warning: passing argument 2 of ‘signal’ from incompatible pointer type [enabled by default]
    /usr/include/signal.h:101:23: note: expected ‘__sighandler_t’ but argument is of type ‘int (*)()’

    Der Code:

    #include <errno.h>
    #include <stdio.h>
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <signal.h>
    #include <stdlib.h>
    #include <string.h>
    
    #define FINS_UDP_PORT 9600
    #define SERV_IP_ADDR "192.168.1.10" /*Ethernet Unit IP ADDRESS */
    #define MAX_MSG 2010
    #define RESP_TIMEOUT 2
    
    /*
    * FINS COMMUNICATIONS SAMPLE PROGRAM
    */
    
    main(argc,argv) 
    int argc;
    char *argv[];
    {
    
    	int sockfd;
    	struct sockaddr_in ws_addr,cv_addr;
    	char fins_cmnd[MAX_MSG],fins_resp[MAX_MSG];	
    	int sendlen,recvlen,addrlen;
    	char sid=0;
    	extern recv_fail();
    
    	/* GENERATE UDP SOCKET */
    	if((sockfd=socket(AF_INET,SOCK_DGRAM,0))<0) {
    		err_exit("can’t open datagram socket");
    	}
    
    	/* ALLOCATE IP ADDRESS AND PORT# TO SOCKET */
    	bzero((char*)&ws_addr,sizeof(ws_addr));
    	ws_addr.sin_family=AF_INET;
    	ws_addr.sin_addr.s_addr=htonl(INADDR_ANY);
    	ws_addr.sin_port=htons(FINS_UDP_PORT);
    	if(bind(sockfd,(struct sockaddr*)&ws_addr,sizeof(ws_addr))<0) {
    		err_exit("cant bind local address");
    	}
    
    	/*
    	* GENERATE MEMORY AREA READ COMMAND
    	* (READ 150 WORDS FROM D00100.)
    	*/
    
    	fins_cmnd[0]=0x80; /*ICF*/
    	fins_cmnd[1]=0x00; /*RSV*/
    	fins_cmnd[2]=0x02; /*GCT*/
    	fins_cmnd[3]=0x01; /*DNA*/
    	fins_cmnd[4]=0x11; /*DA1*/ /*Ethernet Unit FINS NODE NUMBER*/
    	fins_cmnd[5]=0x00; /*DA2*/
    	fins_cmnd[6]=0x01; /*SNA*/
    	fins_cmnd[7]=0x0B; /*SA1*/ /* WS FINS NODE NUMBER */
    	fins_cmnd[8]=0x00; /*SA2*/
    	fins_cmnd[9]=++sid; /*SID*/
    	fins_cmnd[10]=0x01; /*MRC*/
    	fins_cmnd[11]=0x01; /*SRC*/
    	fins_cmnd[12]=0x82; /*VARIABLE TYPE: DM*/
    	fins_cmnd[13]=0x00; /*READ START ADDRESS: 100*/
    	fins_cmnd[14]=0x64;
    	fins_cmnd[15]=0x00;
    	fins_cmnd[16]=0x00; /*WORDS READ: 150*/
    	fins_cmnd[17]=0x96;
    
    	/*SEND FINS COMMAND*/
    
    	bzero((char*)&cv_addr,sizeof(cv_addr));
    	cv_addr.sin_family=AF_INET;
    	cv_addr.sin_addr.s_addr=inet_addr(SERV_IP_ADDR);
    	cv_addr.sin_port=htons(FINS_UDP_PORT);
    
    	signal(SIGALRM,recv_fail);
    
    CMND_SEND:
    	sendlen = 18;
    	if(sendto(sockfd,fins_cmnd,sendlen,0,(struct sockaddr *)&cv_addr,sizeof(cv_addr))==sendlen){
    		alarm(RESP_TIMEOUT); /*START RESPONSE MONITOR TIMER*/
    		printf("send length %d \n",sendlen);
    	}
    	else { 
    		err_exit("send error");
    	}
    
    	/*RECEIVE FINS RESPONSE*/
    
    	if((recvlen = recvfrom(sockfd,fins_resp,MAX_MSG,0,(struct sockaddr *)&cv_addr,&addrlen))<0) {
    		if(errno == EINTR) {
    			goto CMND_SEND; /*RE-SEND FINS COMMAND*/
    		}
    		err_exit("receive error");
    	}
    	else {
    		alarm(0); /*STOP RESPONSE MONITOR TIMER*/
    		printf("recv length %d \n",recvlen);
    		if(recvlen<14) { /*ILLEGAL RESPONSE LENGTH CHECK*/
    			err_exit("FINS length error");
    		}
    		if((fins_cmnd[3]!=fins_resp[6])||(fins_cmnd[4]!=fins_resp[7])||(fins_cmnd[5]!=fins_resp[8])) { /*DESTINATION ADDRESS CHECK*/
    			err_exit("illegal source address error");
    		}
    		if(fins_cmnd[9]!=fins_resp[9]) { /*SID CHECK*/
    			err_exit("illegal SID error");
    		}
    	}
    
    	/*CLOSE SOCKET*/
    	close(sockfd);
    return 0;
    }
    
    /*
    *ERROR PROCESSING FUNCTIONS
    */
    err_exit(err_msg)
    char *err_msg;
    {
    	printf("client: %s %x \n",err_msg,errno);
    	exit(EXIT_FAILURE);
    }
    
    /*
    *SIGNAL CAPTURE FUNCTIONS
    */
    recv_fail()
    {
    	printf("response timeout error \n");
    	return 0;
    }
    

    Leider weiß ich jetzt absolut nicht weiter...
    Bei der Ausführung des Codes kommt momentan folgende Ausgabe:

    send length 18
    recv length 16

    Wie kann ich mir die ankommenden Zeichen ausgeben lassen?



  • tntnet schrieb:

    EINTR bedeutet hier, dass der Systemaufruf recvfrom unterbrochen wurde. Die Daten wurden aber dennoch gesendet. Daher solltest Du nur den Systemaufruf wiederholen und nicht das Senden. Da hast Du es auch leichter dieses (würg) goto zu entfernen.

    Und wie genau setz ich das um?
    Wie kann ich mir die ankommende Zeichenkette anzeigen lassen?



  • Indem du die Programmiersprache lernst! pfosten


Log in to reply