2017-04-22 2 views
0

Das Problem ist, dass der Server unabhängig von dem Port, den ich festgelegt habe, eine Verbindung zu einem anderen herstellt. Zum Beispiel, in meinem Code habe ich den Port 20000 (aber ich habe auch andere Zahlen versucht), aber wenn ich die Portnummer drucken ist es völlig anders (jetzt zeigt es 8270) ist diese Zeile korrekt? indirizzo_serv.sin_port=htons(20000);TCP-Server bindet nicht an bestimmten Port

ein anderes Problem ist, dass der Server nicht akzeptiert mehrere Befehle, ich meine, wenn ich "Zeit" senden und die Antwort bekommen, dann kann ich keinen anderen Befehl senden. Server-Code:

#include<stdio.h> 
#include<stdlib.h> 
#include<string.h> 
#include<sys/socket.h> 
#include<netinet/in.h> 
#include<unistd.h> 
#include<netinet/in.h> 
#include<arpa/inet.h> 
#include<time.h> //per data e ora 
#include<locale.h> //per la traduzione di giorno e mese 


int main(void) 
{ 
char buf[100]={0},tmp[10]={0}; 
time_t t; //tempo "grezzo" (rawtime) 
struct tm *info; //struttra che contiene le informazioni su data e ora 
struct sockaddr_in indirizzo_serv; 
int fd1,fd2; 
socklen_t len; 

setlocale(LC_ALL,"it_IT.utf8"); //per stampare giorno e mese in italiano, ricavato dando da terminale locale -a 

indirizzo_serv.sin_family=AF_INET; 
indirizzo_serv.sin_port=htons(20000); 
indirizzo_serv.sin_addr.s_addr=htonl(INADDR_ANY); 
fd1=socket(PF_INET,SOCK_STREAM,0); //socket tcp di rete 
bind(fd1,(struct sockaddr*)&indirizzo_serv,sizeof(indirizzo_serv)); 
listen(fd1,5); 

sprintf(tmp,"Numero porta= %d\n",indirizzo_serv.sin_port); 
write(STDOUT_FILENO,tmp,strlen(tmp)); 
bzero(tmp,10); 

fd2=accept(fd1,NULL,NULL); 

sleep(2); 

while(1){ 
    read(fd2,buf,100); 
    if((strcmp(buf,"TIME\n"))==0){ 
     time(&t); 
     info=localtime(&t); 
     strftime(buf,100,"Sono le ore %H.%M%n",info); 
     write(fd2,buf,strlen(buf)); 
     bzero(buf,100); 
    } 
    else if((strcmp(buf,"DATE\n"))==0){ 
     time(&t); 
     info=localtime(&t); 
     strftime(buf,100,"Oggi è %A, %e %B %G %n",info); 
     write(fd2,buf,strlen(buf)); 
     bzero(buf,100); 
    } 
    else if((strcmp(buf,"PORT\n"))==0){ 
     indirizzo_serv.sin_port=htons(0); //porta casuale 
     len=sizeof(indirizzo_serv); 
     getsockname(fd1,(struct sockaddr*)&indirizzo_serv,&len); 
     sprintf(tmp,"Numero porta= %d\n",indirizzo_serv.sin_port); 
     write(STDOUT_FILENO,tmp,strlen(tmp)); 
     write(fd2,tmp,strlen(tmp)); //invio la porta al client sotto forma di stringa 
     bzero(tmp,10); 
    } 
} 

close(fd1); 
return 0; 
} 

Client-Code:

#include<stdio.h> 
#include<stdlib.h> 
#include<string.h> 
#include<sys/socket.h> 
#include<netinet/in.h> 
#include<unistd.h> 
#include<netinet/in.h> 
#include<arpa/inet.h> 
#include<ctype.h> //per toupper 

int main(void) 
{ 
struct sockaddr_in indirizzo; 
int fd,i=0,nport; 
char buf[100]={0}; 

indirizzo.sin_family=AF_INET; 
inet_aton("127.0.0.1",&indirizzo.sin_addr); 
indirizzo.sin_port=htons(10000); 

fd=socket(PF_INET,SOCK_STREAM,0); 

connect(fd,(struct sockaddr*)&indirizzo,sizeof(indirizzo)); 

while(1){ 
    write(STDOUT_FILENO,"Scrivi il comando da inviare al server tra i seguenti: TIME, DATE, PORT.\n",strlen("Scrivi il comando da inviare al server tra i seguenti: TIME, DATE, PORT.\n")); 
    read(STDIN_FILENO,buf,sizeof(buf)); 
    while(buf[i]){ 
     buf[i]=toupper(buf[i]); 
     i++; 
    } 
    if((strcmp(buf,"PORT\n"))==0){ 
      bzero(buf,100); 
      read(fd,buf,sizeof(buf)); 
      nport=atoi(buf); 
      indirizzo.sin_port=htons(nport); 
      connect(fd,(struct sockaddr*)&indirizzo,sizeof(indirizzo)); 

    } 
    write(fd,buf,strlen(buf)); //incio comando al server 
    bzero(buf,100); 
    read(fd,buf,100); //leggo il messaggio ricevuto dal server 
    write(STDOUT_FILENO,buf,strlen(buf)); //stampo a video il messaggio 
    bzero(buf,100); 
} 

close(fd); 
return 0; 

} 

Antwort

1

Mit

sprintf(tmp,"Numero porta= %d\n",indirizzo_serv.sin_port); 

Sie erstellen eine Zeichenfolge mit dem Netzwerk-Byte-Reihenfolge Wert des Ports. Sie müssen die Host-Byte-Reihenfolge ntohs mit bekommen:

sprintf(tmp,"Numero porta= %d\n",ntohs(indirizzo_serv.sin_port)); 

Netzwerk-Byte-Reihenfolge ist big endian während ein moderner x86 (oder x86_64) basierter PC little endian ist. Dies ist der wahrscheinlichste Grund für Ihr Problem.

Die htons konvertieren einen short Wert von Host-Byte-Reihenfolge in Netzwerk-Byte-Reihenfolge, und die ntohs macht das Gegenteil.

0

Dies ist, weil Sie die Portnummer drucken, die in Netzwerk Format ist. Ihre Maschine ist sicherlich Little-Endian, was bedeutet, dass Bytes zur Darstellung von Zahlen im Gegensatz zur Netzwerkordnung stehen.

Da Sie 20000 angegeben, in Netzwerk-Bestellung dies als 0x4E20 (hexadezimal Basis) dargestellt wird, aber das Gerät liest sie von rechts nach links, so 0x204E liest die 8270 ist.

Dann verwenden Sie ntohs(), um es zurück zu konvertieren.

0

Vielleicht nicht streng in diesem Fall beteiligt, aber im Server-Code deklariert tmp [10] und später Sie Sprintf viel mehr als 10 Bytes, überschreiben auch * info und indirizzo_serv.

Verwandte Themen