accept mit AF_INET liefert sockaddr_in-Objekt, dass inet_pton nicht immer lesen kann



  • Hallo, Leute.
    Ich habe hier ein merkwürdiges Problem mit einem selbstgeschriebenen TCP-Server unter Linux (Ubuntu/Debian, jeweils Kernel 2.6.32-48/3.7 (selbstkompiliert), jeweils i686/x86_64).

    Szenario:
    Ich erstelle einen AF_INET-Socket für verbindungsbasierte Kommunikation und binde diesen dann an einen Port. Den laufenden Prozess spreche ich dann mit telnet 127.0.0.1 1337 an. Auf meiner Ubuntu-Maschine wird dann immer ausgegeben, dass die Network-Family AF_INET aka 2 ist, auf meiner Debian-Maschine gibt der allererste Connect zum Server allerdings eine Network-Family von 0 an - was er nicht ist. Beim zweiten Connect erhalte ich dann die richtige Family.

    Aber noch was: auch die Peer-IP ist auf der x86_64-Maschine beim ersten Laden kaputt, nach dem zweiten Laden ist sie korrekt.

    Ich habe daher einmal folgendes Szenario durchgeführt:
    Code auf einer i686-Maschine kompiliert, laufen lassen.
    Code auf einer x64-Maschine kompiliert, laufen lassen.
    telnet auf der i686-Maschine aufrufen lassen, auf den x64er connected- hat mir das hier ausgegeben:

    Attempting to convert address 192.168.0.250, port 1337 ...
    Bind address 192.168.0.250 successfully converted to network form 4194347200|fa00a8c0 ...
    Network form of port 1337 is 14597 ...
    Socket 3 successfully created ...
    Socket 3 successfully binded ...
    Socket 3 is listening now ...
    New incomming request from peer 0|16 ...
    Peer address is 0.0.0.0 ... # und das ist falsch, sollte 192.168.0.215 sein.
    

    telnet auf der x64-Maschine aufrufen lassen, auf den i686 connected- hat mir das hier ausgegeben:

    Attempting to convert address 192.168.0.215, port 1337 ...
    Bind address 192.168.0.215 successfully converted to network form 3607144640|d700a8c0 ...
    Network form of port 1337 is 14597 ...
    Socket 3 successfully created ...
    Socket 3 successfully binded ...
    Socket 3 is listening now ...
    New incomming request from peer 2|16 ...
    Peer address is 192.168.0.250 ..
    

    Code kompiliert mit g++ -O2 text.cpp -o program

    #include <cstdio>
    #include <cstring>
    
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <unistd.h>
    
    #include <netinet/in.h>
    #include <arpa/inet.h>
    
    int main()
    {
    	int yes=1;
    
    	char*source="127.0.0.1";
            int port=1337;
    
            struct sockaddr_in bind_addr;
            bind_addr.sin_family	=AF_INET;
            bind_addr.sin_port	=htons(port);
    
    	printf("Attempting to convert address %s, port %u ...\n",source,port);
    
    	if(!inet_pton(AF_INET,source,&bind_addr.sin_addr))
    	{
    		fprintf(stderr,"Couldn't convert address %s into network address\n",source);
    		return 1;
    	}
    
    	printf("Bind address %s successfully converted to network form %u|%x ...\n",source,bind_addr.sin_addr,bind_addr.sin_addr);
    	printf("Network form of port %u is %u ...\n",port,htons(port));
    
    	int sock=socket(bind_addr.sin_family,SOCK_STREAM,0);
    
    	if(sock==-1)
    	{
    		printf("%u|%u|%u\n",bind_addr.sin_family,SOCK_STREAM,0);
    		perror("socket");
    		return 2;
    	}
    
    	if(setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,&yes,sizeof(int))==-1)
    	{
    		perror("setsockopt");
    		return 3;
    	}
    
    	printf("Socket %u successfully created ...\n",sock);
    
    	if(bind(sock,(struct sockaddr*)&bind_addr,sizeof(struct sockaddr_in))==-1)
    	{
    		perror("bind");
    		return 4;
    	}
    
    	printf("Socket %u successfully binded ...\n",sock);
    
    	if(listen(sock,20)==-1)
    	{
    		perror("listen");
    		return 5;
    	}
    	printf("Socket %u is listening now ...\n",sock);
    
    	int		peer_sock;
    	struct sockaddr_storage	peer_addr;
    	struct sockaddr_in*peer_addr_in;
    	socklen_t	peer_addr_len;
    
    	char str[INET6_ADDRSTRLEN];
    
    	while(peer_sock=accept(sock,(struct sockaddr*)&peer_addr,&peer_addr_len))
    	{
    		peer_addr_in=(struct sockaddr_in*)&peer_addr;
    		inet_ntop(bind_addr.sin_family,&peer_addr_in->sin_addr,str,sizeof(*peer_addr_in));
    		printf("New incomming request from peer %u|%u ...\n",peer_addr.ss_family,peer_addr_len);
    		printf("Peer address is %s ...\n",str);
    		close(peer_sock);
    	}
    
    	close(sock);
    	return 0;
    }
    

    Kann mir mal einer verraten, wieso es auf der x64-Maschine nicht tut? Die Ironie ist, ich habe das Ding ursprünglich auf einer x64-Maschine geschieben und durch Zufall rausgefunden, dass es auf der i686-Maschine wunderbar tut.



  • port sollte unsigned short sein!


Anmelden zum Antworten