2017-04-22 50 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。

相关问题