当前位置: 首页 > 知识库问答 >
问题:

unix套接字数据报:服务器接收到无效字符

陆高峰
2023-03-14

我试图创建一个Unix套接字数据报示例。客户端可以流畅地发送和接收消息。在缓冲区长度小于< code>SOCKET_BUFFER_SIZE的情况下,服务器能够做到这一点,否则服务器的输出会在接收的缓冲区显示一些无效字符。

客户代码

#include "ud_hdr.h"

#define IN_BUF_SIZE     200

int main(int argc, char **argv)
{
    struct sockaddr_un  svr_addr, cli_addr;
    int                 sfd, i;
    ssize_t             num_rw;
    socklen_t           svr_addr_len;
    char                sock_buf[SOCK_BUF_SIZE];
    char                in_buf[IN_BUF_SIZE];

    // Create sockets:
    sfd = socket(AF_UNIX, SOCK_DGRAM, 0);
    if (sfd == -1) {
        printf("Error line|%d|: %s", __LINE__, strerror(errno));
        exit(EXIT_FAILURE);
    }

    // ! In Unix domain, the client needs to assign an address to its socket
    // ! if it wants to RECEIVE datagrams sent by server.
    memset(&cli_addr, 0, sizeof(struct sockaddr_un));
    cli_addr.sun_family = AF_UNIX;
    snprintf(cli_addr.sun_path, sizeof(cli_addr.sun_path), \
            "/tmp/dxduc/ud_cli.%ld", (long)getpid());
    if (bind(sfd, (struct sockaddr *) &cli_addr, sizeof(struct sockaddr_un)) == -1) {
        printf("Error line|%d|: %s\n", __LINE__, strerror(errno));
        exit(EXIT_FAILURE);
    }

    // Construct server's address:
    memset(&svr_addr, 0, sizeof(struct sockaddr_un));
    svr_addr.sun_family = AF_UNIX;
    strncpy(svr_addr.sun_path, SOCKET_SV_PATH, sizeof(svr_addr.sun_path) - 1);

    printf("Client is ready to run\n");
    while (1) {
        printf("Enter new msg: ");
        fflush(stdout); // * clear the output buffer and move the buffered data to output (a.k.a console in this case)
        memset(in_buf, 0, sizeof(in_buf));
        memset(sock_buf, 0, sizeof(sock_buf));
        num_rw = read(STDIN_FILENO, in_buf, IN_BUF_SIZE);

        // Remove '\n' and '\r' in input:
        for (i = 0; i < IN_BUF_SIZE; i++) {
            // if ((in_buf[i] == '\r') || (in_buf[i] == '\n')) {
            if (in_buf[i] == '\n') {
                in_buf[i] = 0x0;
            }
        }

        printf("Msg to server: |%s|, len = %ld, num_rw = %ld\n", in_buf, strlen(in_buf), num_rw);
        svr_addr_len = sizeof(struct sockaddr_un);
        if (num_rw > 0) {
            // Send msg to server:
            if (sendto(sfd, in_buf, strlen(in_buf), 0, (struct sockaddr *) &svr_addr, svr_addr_len) != strlen(in_buf)) {
                printf("Error line|%d|: %s\n", __LINE__, strerror(errno));
                exit(EXIT_FAILURE);
            }
        } else if (num_rw == 0) {
            printf("Nothing to send to server\n");
            continue;
        } else if (num_rw == -1) {
            printf("Error line|%d|: %s\n", __LINE__, strerror(errno));
            exit(EXIT_FAILURE);
        }

        // Read response from server
        num_rw = recvfrom(sfd, sock_buf, SOCK_BUF_SIZE, 0, (struct sockaddr *) &svr_addr, &svr_addr_len);
        if (num_rw == -1) {
            printf("Error line|%d|, %s", __LINE__, strerror(errno));
            exit(EXIT_FAILURE);
        } else {
            printf("Receive from server: |%s|, len=%ld, num_rw=%ld\n", sock_buf, strlen(sock_buf), num_rw);
        }
    }
}

服务器的代码

#include "ud_hdr.h"

int main(int argc, char **argv)
{
    struct sockaddr_un  svr_addr, cli_addr;
    int                 sfd, i;
    ssize_t             num_rw;
    socklen_t           cli_addr_len;
    char                buf[SOCK_BUF_SIZE];

    // Create socket:
    sfd = socket(AF_UNIX, SOCK_DGRAM, 0);
    if (sfd == -1) {
        printf("Error line|%d|: %s\n", __LINE__, strerror(errno));
        exit(EXIT_FAILURE);
    }

    // Verify socket's name path:
    if (strlen(SOCKET_SV_PATH) > (sizeof(svr_addr.sun_path) - 1)) {
        printf("Error line|%d|: invalid socket name", __LINE__);
        exit(EXIT_FAILURE);
    }

    // Remove any existing file having the same namepath with server's:
    if ((remove(SOCKET_SV_PATH) == -1) && (errno != ENOENT)) {
        printf("Error line|%d|: %s\n", __LINE__, strerror(errno));
        exit(EXIT_FAILURE);
    }

    // Bind the socket to desired addr:
    memset(&svr_addr, 0, sizeof(struct sockaddr_un));
    svr_addr.sun_family = AF_UNIX;
    strncpy(svr_addr.sun_path, SOCKET_SV_PATH, sizeof(svr_addr.sun_path) - 1);

    if (bind(sfd, (struct sockaddr *)&svr_addr, sizeof(struct sockaddr_un)) == -1) {
        printf("Error line|%d|: %s\n", __LINE__, strerror(errno));
        exit(EXIT_FAILURE);
    }

    while (1) {
        // Receive data from client:
        memset(buf, 0, sizeof(buf));
        cli_addr_len = sizeof (struct sockaddr_un);
        num_rw = recvfrom(sfd, buf, SOCK_BUF_SIZE, 0, (struct sockaddr *) &cli_addr, &cli_addr_len);

        if (num_rw == -1) {
            printf("Error line|%d|: %s\n", __LINE__, strerror(errno));
            exit(EXIT_FAILURE);
        }

        printf("Server received %ld bytes from %s, ret_buf=|%s|, len=%ld\n", (long)num_rw, cli_addr.sun_path, buf, strlen(buf));

        // Uppercase received characters:
        for (i = 0; i < num_rw; i++) {
            buf[i] = toupper((unsigned char)buf[i]);
        }

        // Send back uppercase-ed characters to client:
        printf("Send back to client: |%s|, len=%ld\n", buf, strlen(buf));
        if (sendto(sfd, buf, strlen(buf), 0, (struct sockaddr *) &cli_addr, cli_addr_len) != strlen(buf)) {
            printf("Error line|%d|: %s\n", __LINE__, strerror(errno));
            exit(EXIT_FAILURE);
        }
    }
}

头文件

#ifndef _UD_HDR_H_
#define _UD_HDR_H_

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>

#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>

#include <errno.h>
#include <unistd.h>
#include <ctype.h>

// * The Makefile should have created /tmp/dxduc before run this program
#define SOCKET_SV_PATH      "/tmp/dxduc/ud_basic"
#define SOCK_BUF_SIZE            10

#endif // _UD_HDR_H_

这是我得到的

# Client
Client is ready to run
Enter new msg: stack  
Msg to server: |stack|, len = 5, num_rw = 6
Receive from server: |STACK|, len=5, num_rw=5
Enter new msg: stackoverflow
Msg to server: |stackoverflow|, len = 13, num_rw = 14
Receive from server: |STACKOVERF|, len=10, num_rw=10

#Server
Server received 5 bytes from /tmp/dxduc/ud_cli.2385, ret_buf=|stack|, len=5
Send back to client: |STACK|, len=5
Server received 10 bytes from /tmp/dxduc/ud_cli.2385, ret_buf=|stackoverf�  |, len=14
Send back to client: |STACKOVERF�   |, len=14

奇怪的是,客户端收到了预期的消息,尽管服务器在发送之前没有正确格式化消息。

这是我的预期输出

# Client
Client is ready to run
Enter new msg: stack  
Msg to server: |stack|, len = 5, num_rw = 6
Receive from server: |STACK|, len=5, num_rw=5
Enter new msg: stackoverflow
Msg to server: |stackoverflow|, len = 13, num_rw = 14
Receive from server: |STACKOVERF|, len=10, num_rw=10

#Server
Server received 5 bytes from /tmp/dxduc/ud_cli.2385, ret_buf=|stack|, len=5
Send back to client: |STACK|, len=5
Server received 10 bytes from /tmp/dxduc/ud_cli.2385, ret_buf=|stackoverf|, len=10
Send back to client: |STACKOVERF|, len=14

我该如何解决?

共有1个答案

南宫泓
2023-03-14

您的SOCK_BUF_SIZE为 10,您收到 10 个字节(在您的客户端中)。它会覆盖您的 0 字节。你应该使用

char sock_buf[SOCK_BUF_SIZE+1];
 类似资料:
  • 因此,我正在用Java编写一个程序,在DatagramSocket和DataGramPacket的帮助下发送和接收数据。问题是,当我发送数据/接收数据时,数据在我发送的程序中也会有所不同,但只是在某些情况下,比如: 但有时会起作用,比如:

  • 首先我要感谢你花时间... 我在macbook中用C++创建了一个服务器套接字,在运行windows XP的不同机器中用Java创建了一个客户机/套接字。我已将端口指定为5000,但无法指定正确的主机,因此无法进行连接。当我在windows xp中使用WinSock2创建一个C++服务器/套接字时,当我使用本地主机时,连接是完美的...有什么想法吗??? 提前Thnx int main(int a

  • 我有一个Python服务器使用unix数据报套接字连接与一个C客户端通信。下面的代码设置一个套接字,然后从客户端发送和接收一条消息。这个脚本在python 2.7中工作,但是,当在python 3中测试它时,对recv()的调用会超时等待来自客户端的消息。然而,客户端确实从服务器接收消息而没有问题。我已经用3.5.2和3.7.1在两台不同的机器上测试过了,结果相同。 更新:我添加了一个ioloop

  • 我编写了一个简单的java套接字服务器。我可以使用java客户端连接到它。 但是,当我尝试将android设备连接到它时,它会给出以下错误: 代码如下: 这一行:似乎是罪魁祸首。 错误消息“java.net.socketexception:套接字失败:EACCES(权限被拒绝)” Android java.net.SocketException:套接字失败:EACCES(拒绝权限) Android

  • 线程“main”java.net.ConnectException:连接超时:在java.net.dualStackplainsockeTimpl.Connect0(本机方法)在java.net.dualStackplainsockeTimpl.socketConnect(DualStackplainsockeTimpl.java:69)在java.net.abstractplainsockeTi

  • 我正在编写原始套接字客户端(成功发送UDP数据包)和一个服务器套接字,问题出在服务器部分。 Im按以下方式创建套接字: