问题在于无论我设置什么端口,服务器都连接到另一个端口。
例如,在我的代码中我设置了端口20000(但我也尝试了其他数字),但是当我打印端口号时它完全不同(现在它显示了8270)
这条线是否正确? indirizzo_serv.sin_port=htons(20000);
另一个问题是服务器不接受多个命令,我的意思是当我发送" time"并得到答案,然后我不能发送任何其他命令。服务器代码:
#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;
}
答案 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。这是您遇到问题的最可能原因。
htons
将short
值从主机字节顺序转换为网络字节顺序,ntohs
执行相反的操作。
答案 1 :(得分:0)
这是因为您打印的是网络格式的端口号。你的机器当然是little-endian,这意味着代表数字的字节与网络排序相反。
由于您指定了20000
,因此在网络排序中,这表示为0x4E20
(十六进制),但您的计算机从右向左读取它,因此请0x204E
读取8270
1}}。
然后使用ntohs()
将其转换回来。
答案 2 :(得分:0)
在这种情况下可能没有严格的参与,但在服务器代码中你声明了tmp [10],之后你sprintf超过10个字节,也覆盖* info和indirizzo_serv。