tcp服务器没有绑定到特定端口

时间:2017-04-22 10:52:23

标签: c sockets unix tcp

问题在于无论我设置什么端口,服务器都连接到另一个端口。 例如,在我的代码中我设置了端口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;

}

3 个答案:

答案 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执行相反的操作。

答案 1 :(得分:0)

这是因为您打印的是网络格式的端口号。你的机器当然是little-endian,这意味着代表数字的字节与网络排序相反。

由于您指定了20000,因此在网络排序中,这表示为0x4E20(十六进制),但您的计算机从右向左读取它,因此请0x204E读取8270 1}}。

然后使用ntohs()将其转换回来。

答案 2 :(得分:0)

在这种情况下可能没有严格的参与,但在服务器代码中你声明了tmp [10],之后你sprintf超过10个字节,也覆盖* info和indirizzo_serv。