[英]unix socket datagram: server receive invalid characters
I'm trying to create a Unix socket datagram example.我正在尝试创建一个 Unix 套接字数据报示例。 The client can send and receive message smoothly.
客户端可以顺利发送和接收消息。 The server is able to do that just in case the buffer length is smaller than
SOCKET_BUFFER_SIZE
, otherwise the server's output shows some invalid characters at received buffer.服务器可以这样做,以防缓冲区长度小于
SOCKET_BUFFER_SIZE
,否则服务器的 output 在接收的缓冲区中显示一些无效字符。
Client's code客户代码
#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);
}
}
}
Server's code服务器的代码
#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);
}
}
}
Header file Header文件
#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_
This is what I got这就是我得到的
# 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
It's weird that the client received the expected message, though the server did not format the message correctly before sending it.很奇怪,客户端收到了预期的消息,尽管服务器在发送之前没有正确格式化消息。
This is my expected output这是我预期的 output
# 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
How should I solve it?我该如何解决?
Your SOCK_BUF_SIZE
is 10 and you receive 10 bytes (in your client).您的
SOCK_BUF_SIZE
为 10,您收到 10 个字节(在您的客户端中)。 It overwrites your 0 byte.它会覆盖您的 0 字节。 You should use
你应该使用
char sock_buf[SOCK_BUF_SIZE+1];
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.