简体   繁体   English

TCP服务器未绑定到特定端口

[英]tcp server not binding to specific port

The problem is that whatever the port I set, the server connects to a different one. 问题是无论我设置了哪个端口,服务器都连接到另一个端口。 For example, in my code I set the port 20000 (but I also tried other numbers), but when I print the port number it's completely different (now it's showing 8270) is this line correct? 例如,在我的代码中,我设置了端口20000(但是我也尝试了其他数字),但是当我打印端口号时,它是完全不同的(现在显示8270),这行正确吗? indirizzo_serv.sin_port=htons(20000);

another issue is that server doesn't accept multiple commands, I mean when I send "time" and get the answer, then I can't send any other command. 另一个问题是服务器不接受多个命令,我的意思是当我发送“时间”并获得答案时,则无法发送任何其他命令。 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;

}

With

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

you create a string containing the network byte order value of the port. 您创建一个包含端口的网络字节顺序值的字符串。 You need to get the host byte order using ntohs : 您需要使用ntohs获取主机字节顺序:

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

Network byte order is big endian while a modern x86 (or x86_64) based PC is little endian . 网络字节顺序是大字节序,而现代的基于x86(或x86_64)的PC是小字节序 This is the most likely reason of your problem. 这是您出现问题的最可能原因。

The htons convert a short value from host byte order to network byte order, and the ntohs does the opposite. htonsshort值从主机字节顺序转换为网络字节顺序,而ntohs则相反。

This is because you print the port number that is in Network format. 这是因为您打印的是网络格式的端口号。 Your machine is certainly little-endian which means that bytes to represent numbers are in the opposite of the network ordering. 您的计算机肯定是低位字节序的,这意味着代表数字的字节与网络顺序相反。

Since you specified 20000 , in Network ordering this is represented as 0x4E20 (hexadecimal basis) but your machine reads it from the right to the left so reads 0x204E which is 8270 . 由于您指定了20000 ,因此在网络顺序中,它表示为0x4E20 (十六进制),但是您的计算机从右到左读取它,因此读取的是0x204E ,即8270

Then use ntohs() to convert it back. 然后使用ntohs()将其转换回。

可能不严格涉及这种情况,但是在服务器代码中,您声明了tmp [10],随后又将sprintf声明为10多个字节,还覆盖了* info和indirizzo_serv。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM