2017-04-22 51 views
0

問題是,無論我設置的端口是什麼,服務器都連接到另一個端口。 例如,在我的代碼中,我設置了端口20000(但我也嘗試了其他數字),但是當我打印端口號時,它完全不同(現在顯示8270) 是這條線是否正確? indirizzo_serv.sin_port=htons(20000);tcp服務器未綁定到特定端口

另一個問題是服務器不接受多個命令,我的意思是當我發送「時間」並得到答案時,我不能發送任何其他命令。服務器代碼:

#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; 
} 

客戶端代碼:

#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; 

} 

回答

1

隨着

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

創建包含端口的網絡字節順序值的字符串。你需要得到使用ntohs主機字節順序:

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

網絡字節順序是big endian而現代的x86(或x86_64)基於PC是little endian。這是你的問題最可能的原因。

htonsshort的值從主機字節順序轉換爲網絡字節順序,而ntohs的做法相反。

0

這是因爲您打印的端口號是網絡格式。你的機器肯定是小端的,這意味着代表數字的字節與網絡排序相反。

既然你指定20000,在網絡訂購此表示爲0x4E20(十六進制爲基礎),但你的機器從向左向右讀它,以便讀取0x204E這是8270

然後用ntohs()將其轉換回來。

0

在這種情況下可能不會嚴格涉及,但是在服務器代碼中,你聲明瞭tmp [10],後來你的sprintf超過了10個字節,覆蓋了* info和indirizzo_serv。

相關問題