注册 登录
编程论坛 VFP论坛

吹佬你的程序只能使用2位端口如80,90 ,而443 8080 等出错?

ljb8864 发布于 2023-08-12 14:43, 900 次点击
    PROCEDURE _SetListen
        LPARAMETERS hWnd, szIP, nPort
        LOCAL stWsaData, stSockAddr
        this._CloseSocket()
        
        this.hWnd  = hWnd
        stWsaData  = REPLICATE(0h00, 398)
        WSAStartup(0x202, @stWsaData)
        this.hSocket = socket(2, 1, 0)
        WSAAsyncSelect(this.hSocket, this.hWnd, WM_SOCKET, 8)    && FD_ACCEPT
        
        stSockAddr = BINTOC(2, "2RS");                   && sin_family
                   + BINTOC(htons(nPort), "2RS");        && sin_port  2RS
                   + BINTOC(inet_addr(@szIP), "4RS");    && sin_addr
                   + REPLICATE(0h00, 8)

        IF _bind(this.hSocket, @stSockAddr, LEN(stSockAddr)) == -1
            RETURN "不能绑定到IP:" + szIP + " 端口:" + TRANSFORM(nPort)
        ELSE
            listen(this.hSocket, 5)                      && 监听,队列限制5
            RETURN "启动服务成功"
        ENDIF
    ENDPROC



怎么优化一下,也可以使用8000 ,或443等端口呢?




struct sockaddr_in {
short int sin_family;  
unsigned short int sin_port;
struct in_addr sin_addr;  
unsigned char sin_zero[8];
};

sin_family:指代协议族,在socket编程中只能是AF_INET
sin_port:存储端口号(使用网络字节顺序)
sin_addr:存储IP地址,使用in_addr这个数据结构
sin_zero:是为了让sockaddr与sockaddr_in两个数据结构保持大小相同而保留的空字节。


而其中in_addr结构的定义如下:
typedef struct in_addr {
union {
struct{ unsigned char s_b1,s_b2, s_b3,s_b4;} S_un_b;
struct{ unsigned short s_w1, s_w2;} S_un_w;
unsigned long S_addr;
} S_un;
} IN_ADDR;
阐述下in_addr的含义,很显然它是一个存储ip地址的共用体有三种表达方式:
第一种用四个字节来表示IP地址的四个数字;
第二种用两个双字节来表示IP地址;
第三种用一个长整型来表示IP地址。
给in_addr赋值的一种最简单方法是使用inet_addr函数,它可以把一个代表IP地址的字符串赋值转换为in_addr类型,如addrto.sin_addr.s_addr=inet_addr("192.168.0.2");
其反函数是inet_ntoa,可以把一个in_addr类型转换为一个字符串。


[此贴子已经被作者于2023-8-12 14:56编辑过]

10 回复
#2
吹水佬2023-08-12 15:12
端口是用16bit存放,8080也只需13bit。
出错有可能是有冲突,是不是已经有应用在使用的端口。

#3
ljb88642023-08-12 15:13
其它语言而且可以绑定多个端口
int main()
{
    int sockfd, newsockfd, portno;
    socklen_t clilen;
    char buffer[256];
    struct sockaddr_in serv_addr, cli_addr;
    int ports[PORTS_COUNT] = {8080, 8888, 9999}; // 需要绑定的端口号
    // 创建TCP套接字
    sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if (sockfd < 0)
        perror("ERROR opening socket");
    // 绑定多个端口
    for (int i = 0; i < PORTS_COUNT; ++i)
    {
        bzero((char *) &serv_addr, sizeof(serv_addr));
        portno = ports[i];
        serv_addr.sin_family = AF_INET;
        serv_addr.sin_addr.s_addr = INADDR_ANY;
        serv_addr.sin_port = htons(portno);
        if (bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0)
            perror("ERROR on binding");
    }
    listen(sockfd, 5);
    clilen = sizeof(cli_addr);
    // 接收客户端连接
    newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen);
    if (newsockfd < 0)
        perror("ERROR on accept");
    bzero(buffer, 256);
    int n = read(newsockfd, buffer, 255);
    if (n < 0)
        perror("ERROR reading from socket");
    printf("Here is the message: %s\n", buffer);
    close(newsockfd);
    close(sockfd);
    return 0;
}
#4
ljb88642023-08-12 15:21
回复 2楼 吹水佬
没有占用的?提示这句出错

        stSockAddr = BINTOC(2, "2RS");                   && sin_family
                   + BINTOC(htons(nPort), "2RS");        && sin_port  2RS  htons(nPort)
                   + BINTOC(inet_addr(@szIP), "4RS");    && sin_addr   反函数是inet_ntoa
                   + REPLICATE(0h00, 8)
#5
吹水佬2023-08-12 15:22
回复 3楼 ljb8864
问题与bind几多个无关吧,bind几多个又如何,有冲突的有用吗?
#6
ljb88642023-08-12 15:25
回复 5楼 吹水佬
BINTOC(htons(8080), "2RS") 这句出错
#7
吹水佬2023-08-12 15:31
以下是引用ljb8864在2023-8-12 15:21:31的发言:

没有占用的?提示这句出错

        stSockAddr = BINTOC(2, "2RS");                   && sin_family
                   + BINTOC(htons(nPort), "2RS");        && sin_port  2RS  htons(nPort)
                   + BINTOC(inet_addr(@szIP), "4RS");    && sin_addr   反函数是inet_ntoa
                   + REPLICATE(0h00, 8)

这句只是字符串问题,可能是BINTOC(),在这没有考虑无符号整数的问题。
测试时最大值最好不要超过0x7FFF(16bit)、0x7FFFFFFF(32bit),否则数值要转换。
这只是一个简单的示例代码,没考虑容错问题,实际应用不能照搬。
#8
吹水佬2023-08-12 15:42
htons函数声明可能有问题,原型in/out参数都是16bit无符号整数
u_short htons(
  [in] u_short hostshort
);

试试:
DECLARE short htons IN Ws2_32 short
#9
吹水佬2023-08-12 15:51
一对的,还有
DECLARE short ntohs IN Ws2_32 short
#10
ljb88642023-08-12 15:53
回复 9楼 吹水佬
成功!完美!
#11
吹水佬2023-08-12 15:56
以下是引用ljb8864在2023-8-12 15:25:37的发言:

BINTOC(htons(8080), "2RS") 这句出错

也可以试试不用htons
BINTOC(8080,"2s")
1