元の Michael Kerrisk のAF_UNIX SOCK_DGRAM サンプル クライアント/サーバー プログラムを変更しようとしています。詳細については、次の 2 つのリンク ( client、server ) をクリックしてください。サンプル コードは、彼の著書The Linux Programming Interface の第 57 章で最初に公開されました。私の目標は、 Kerrisk のコード例に基づいて、「ファイル ソケット」定義を「抽象ソケット」定義に置き換えることです。
残念ながら、私のバージョンのクライアントとサーバーの間で通信を確立できません。もちろん、Kerrisk のバージョンは飛行色で動作します。
私が根本的に間違ったことをしていることは明らかです...しかし...私はそれが何であるかを理解できませんでした。
=================== サーバー ============================= =
「サーバー」のケリスクのコードの私のバージョンは次のとおりです。
int main(int argc, char *argv[])
{
struct sockaddr_un svaddr, claddr;
int sfd, j;
ssize_t numBytes;
socklen_t len;
char buf[BUF_SIZE];
char *abstract_server;
sfd = socket(AF_UNIX, SOCK_DGRAM, 0); /* Create server socket */
if (sfd == -1)
errExit("socket");
abstract_server = "viper_server";
/* Construct well-known address and bind server socket to it */
if (remove(abstract_server) == -1 && errno != ENOENT)
errExit("remove-%s", abstract_server);
memset(&svaddr, 0, sizeof(struct sockaddr_un));
svaddr.sun_family = AF_UNIX;
strncpy(&svaddr.sun_path[1], abstract_server, strlen(abstract_server));
if (bind(sfd, (struct sockaddr *) &svaddr,
sizeof(sa_family_t) + strlen(abstract_server) + 1) == -1)
errExit("bind");
/* Receive messages, convert to uppercase, and return to client */
for (;;) {
len = sizeof(struct sockaddr_un);
numBytes = recvfrom(sfd, buf, BUF_SIZE, 0,
(struct sockaddr *) &claddr, &len);
if (numBytes == -1)
errExit("recvfrom");
printf("Server received %ld bytes from %s\n", (long) numBytes,
claddr.sun_path);
for (j = 0; j < numBytes; j++)
buf[j] = toupper((unsigned char) buf[j]);
if (sendto(sfd, buf, numBytes, 0, (struct sockaddr *) &claddr, len) != numBytes)
fatal("sendto");
}
}
========================= クライアント ======================= ====
これは、 「クライアント」のKerrisk のコードの私のバージョンです。
int main(int argc, char *argv[])
{
struct sockaddr_un svaddr, claddr;
int sfd, j;
size_t msgLen;
ssize_t numBytes;
char resp[BUF_SIZE];
char *abstract_client;
char *abstract_server;
if (argc < 2 || strcmp(argv[1], "--help") == 0)
usageErr("%s msg...\n", argv[0]);
/* Create client socket; bind to unique pathname (based on PID) */
sfd = socket(AF_UNIX, SOCK_DGRAM, 0);
if (sfd == -1)
errExit("socket");
abstract_client = "viper_client";
abstract_server = "viper_server";
memset(&claddr, 0, sizeof(struct sockaddr_un));
claddr.sun_family = AF_UNIX;
strncpy(&claddr.sun_path[1], abstract_client, strlen(abstract_client));
if (bind(sfd, (struct sockaddr *) &claddr,
sizeof(sa_family_t) + strlen(abstract_client) + 1) == -1)
errExit("bind");
/* Construct address of server */
memset(&svaddr, 0, sizeof(struct sockaddr_un));
svaddr.sun_family = AF_UNIX;
strncpy(&svaddr.sun_path[1], abstract_server, strlen(abstract_server));
/* Send messages to server; echo responses on stdout */
for (j = 1; j < argc; j++) {
msgLen = strlen(argv[j]); /* May be longer than BUF_SIZE */
/* code FIX */
if (sendto(sfd, argv[j], msgLen, 0, (struct sockaddr *) &svaddr,
(sizeof(sa_family_t) + strlen(abstract_server) + 1) ) != msgLen)
fatal("sendto");
/* original - non working code - replaced with the code FIX above
if (sendto(sfd, argv[j], msgLen, 0, (struct sockaddr *) &svaddr,
sizeof(struct sockaddr_un)) != msgLen)
{
fatal("sendto");
} */
numBytes = recvfrom(sfd, resp, BUF_SIZE, 0, NULL, NULL);
/* Or equivalently: numBytes = recv(sfd, resp, BUF_SIZE, 0);
or: numBytes = read(sfd, resp, BUF_SIZE); */
if (numBytes == -1)
errExit("recvfrom");
printf("Response %d: %.*s\n", j, (int) numBytes, resp);
}
remove(claddr.sun_path); /* Remove client socket pathname */
exit(EXIT_SUCCESS);
}
テストの開始方法:
> ./server &
> ./client aa bb cc
> result: ERROR: sendto
任意のヘルプ | 提案 | ソリューション | RTFMは大歓迎です
イゴール
PS 私の評判は 10 未満なので、2 つのリンクしか投稿できません (この投稿の上部にある Kerrisk のクライアント URL、Kerrrisk のサーバー URL を参照してください)。そこで、「抽象ソケットの使用方法」のKerrisk のC コード スニペットを「カット アンド ペースト」しました。これは彼の本の 1176 ページ、リスト 57-8 に掲載されています。
int main(int argc, char *argv[])
{
int sockfd;
struct sockaddr_un addr;
char *str;
memset(&addr, 0, sizeof(struct sockaddr_un)); /* Clear address structure */
addr.sun_family = AF_UNIX; /* UNIX domain address */
/* addr.sun_path[0] has already been set to 0 by memset() */
str = "xyz"; /* Abstract name is "\0abc" */
strncpy(&addr.sun_path[1], str, strlen(str));
// In early printings of the book, the above two lines were instead:
//
// strncpy(&addr.sun_path[1], "xyz", sizeof(addr.sun_path) - 2);
// /* Abstract name is "xyz" followed by null bytes */
sockfd = socket(AF_UNIX, SOCK_STREAM, 0);
if (sockfd == -1)
errExit("socket");
if (bind(sockfd, (struct sockaddr *) &addr,
sizeof(sa_family_t) + strlen(str) + 1) == -1)
errExit("bind");
// In early printings of the book, the final part of the bind() call
// above was instead:
// sizeof(struct sockaddr_un)) == -1)
sleep(60);
exit(EXIT_SUCCESS);
}