【问题标题】:how get socket port number from an accept call (C UNIX)如何从接受调用中获取套接字端口号(C UNIX)
【发布时间】:2014-09-15 13:10:54
【问题描述】:

我已经完成了一个简单的客户端/服务器程序,其中服务器等待外部连接,如果客户端的端口号在 [1025-2048] 范围内,则返回连接套接字,否则返回 -1。问题是当我通过客户端地址获取端口号(应该存储在sockaddr 结构中)时,它告诉我客户端端口号为零,但在客户端程序中我已将客户端端口号设置为1999 年。

服务器

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/signal.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <errno.h>


int function(int fd_socket) {

    int fd_socket_acc;
    int len;
    int port;
    struct sockaddr_in client_addr;

    puts("WAITING FOR CLIENT...");

    fd_socket_acc = accept(fd_socket, (struct sockaddr*)&client_addr, &len);

    puts("CONNECTION DONE.");

    port = ntohs (client_addr.sin_port);
    printf("client port number: %d \n", port);


    if (port >= 1024 && port <= 2048) {

        close (fd_socket_acc);
        return fd_socket_acc;
    }   
    else {
        close(fd_socket_acc);
        return -1;
    }
}

int main(int argc, char *argv[]) {


    int fd_socket;
    struct sockaddr_in local_addr;

    fd_socket = socket(AF_INET, SOCK_STREAM, 0);

    local_addr.sin_family = AF_INET;
    local_addr.sin_port = htons(1887);
    local_addr.sin_addr.s_addr = INADDR_ANY;

    bind(fd_socket, (struct sockaddr*)&local_addr, sizeof(local_addr));

    listen(fd_socket, 3);

    function(fd_socket);

    //close(fd_socket);

}

客户

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/signal.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <errno.h>

int main(int argc, char *argv[]) {

    int fd_socket;
    struct sockaddr_in local_addr;
    struct sockaddr_in server_addr;
    struct hostent *hp;

    fd_socket = socket(AF_INET, SOCK_STREAM, 0);

    local_addr.sin_family = AF_INET;
    local_addr.sin_port = htons(1999);
    local_addr.sin_addr.s_addr = INADDR_ANY;

    bind(fd_socket, (struct sockaddr*)&local_addr, sizeof(local_addr));

    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(1887);
    //hostname is "ubuntu"
    hp = gethostbyname("ubuntu");
    bcopy(hp->h_addr, &server_addr.sin_addr, 4);

    printf("%d \n", ntohs(local_addr.sin_port));

    connect(fd_socket, (struct sockaddr*)&server_addr, sizeof(server_addr));

    wait(2);

    close(fd_socket);

}

如果我用printf("%d", ntohs(local_addr.sin_port)) 获得客户端的端口号,它会正确标记1999,但如果我用printf("%d", ntohs(client_addr.sin_port)) 获得服务器中的客户端端口号,它会标记0。为什么?

提前致谢!

【问题讨论】:

  • 为什么要在客户端代码中绑定套接字?它不是客户端和服务器通信中的逻辑。如果客户端和服务器端口相同,则仅建立连接,您可以验证其他端口。
  • 如果您的客户端也有多个接口。
  • 是的,在客户端绑定是没用的。我只是用它来将客户端套接字端口设置为特定的数字以进行测试
  • 出于什么目的?您不应尝试以任何方式控制客户端端口号。它不会完成任何有用的事情,只会让客户端更难(很多)编写。

标签: c sockets unix port


【解决方案1】:

为了从client_addraccept 中获取客户端端口号,您必须通过设置告诉accept 该缓冲区有多大

socklen_t len = sizeof(client_addr);

您也可以通过稍后调用来检索它

len = sizeof(client_addr);
getpeername(fd_socket_acc, (struct sockaddr*)&client_addr, &len);

【讨论】:

  • 是的,问题是 len 变量未初始化。非常感谢!
【解决方案2】:

可能是因为您没有将变量 len 设置为任何值,我怀疑您的编译器将其设置为 0。
发生的情况是您尝试接受未定义的镜头大小。

在调用 accept 之前添加 len=sizeof( struct sockaddr_in ); 将有助于正确填写传递的 client_addr。

【讨论】:

  • 是的,问题是 len 变量未初始化。非常感谢!
猜你喜欢
  • 2012-06-12
  • 2015-02-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-04-27
  • 2017-08-11
  • 2010-10-22
  • 2015-10-25
相关资源
最近更新 更多