これに似た動作を取得したいと思います。
問題は、関数excCommand( "help")を実行すると、ほんの少しのテキストが受信されて印刷されることです。私のテキストファイルはこれです:
COMMAND HELP:
help - Display help
quit - Shutdown client
cOMMAND HELPのみが出力されます。別の問題は、コマンドを入力したときに何も出力されず、2つのコマンドクライアントが終了することです。これは特に作品です:
while (quit)
{
getLine("client> ", command, 10);
if (strcmp(command, "quit") == 0)
quit = 0;
else
excCommand(command);
}
これはサーバーです:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "common.h"
int main(int argc, char *argv[])
{
if (argc != 2)
ErrorWithUserMessage("Parameter(s)", "<Server Port>");
char *service = argv[1];
int servSock = SetupTCPServerSocket(service);
if (servSock < 0)
ErrorWithUserMessage("SetupTCPServerSocket() failed: ", "unable to establish");
unsigned int childProcessCount = 0;
while (1)
{
int clntSock = AcceptTCPConnection(servSock);
pid_t processID = fork();
if (processID < 0)
ErrorWithSystemMessage("fork() failed");
else if (processID == 0)
{
close(servSock);
HandleTCPClient(clntSock);
exit(EXIT_SUCCESS);
}
printf("with child process: %d\n", processID);
close(clntSock);
childProcessCount++;
//clean up zombies
while (childProcessCount)
{
processID = waitpid((pid_t) - 1, NULL, WNOHANG);
if (processID < 0)
ErrorWithSystemMessage("waitpid() failed");
else if (processID == 0)
break;
else
childProcessCount--;
}
}
}
ハンドラ:
void HandleTCPClient(int clntSock)
{
char buffer[BUFSIZE];
ssize_t numBytesRcvd = recv(clntSock, buffer, BUFSIZE, 0);
buffer[numBytesRcvd] = '\0';
if (numBytesRcvd < 0)
ErrorWithSystemMessage("recv() failed");
if (strcmp(buffer, "help") == 0)
{
FILE *fp = fopen("help.txt", "r");
if (fp)
{
char line[128];
while (fgets(line, sizeof(line), fp) != NULL)
{
if (send(clntSock, line, sizeof(line), 0) < 0)
ErrorWithSystemMessage("send() failed");
}
fclose(fp);
}
}
close(clntSock);
}
これが私のクライアントです:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include "common.h"
int sock;
void getLine(char *message, char *buf, int maxLen)
{
printf("%s", message);
fgets(buf, maxLen, stdin);
buf[strlen(buf) - 1] = 0;
}
void excCommand(char *command)
{
if ( send(sock, command, strlen(command), 0) < 0)
ErrorWithSystemMessage("send() failed");
char replyMessage[BUFSIZE];
ssize_t numBytesRecv = 0;
do
{
numBytesRecv = recv(sock, replyMessage, BUFSIZE, 0);
if ( numBytesRecv < 0)
ErrorWithSystemMessage("recv() failed");
printf("%s\n", replyMessage);
memset(&replyMessage, 0, sizeof(replyMessage));
}
while (numBytesRecv > 0);
}
void PrintFile(const char *filename)
{
FILE *fp;
fp = fopen(filename, "r");
if (fp)
{
char line[128];
while (fgets(line, sizeof(line), fp) != NULL)
fputs(line, stdout);
fputs("\n", stdout);
fclose(fp);
}
}
int main(int argc, char *argv[])
{
int quit = 1;
char command[10];
if (argc < 2 || argc > 3)
{
ErrorWithUserMessage("Parameter(s)", "<Server Address> <Server Port>");
}
char *server = argv[1];
char *service = argv[2];
sock = SetupTCPClientSocket(server, service);
if (sock < 0)
ErrorWithUserMessage("SetupTCPClientSocket() failed: ", "unable to connect");
printf("Connection established!\n\n");
PrintFile("menu.txt");
excCommand("help");
while (quit)
{
getLine("client> ", command, 10);
if (strcmp(command, "quit") == 0)
quit = 0;
else
excCommand(command);
}
fputs("\n", stdout);
close(sock);
exit(EXIT_SUCCESS);
}
とても長い間ごめんなさい
recv()
およびsend()
関数は、すべてのデータの送信/受信を保証するものではありません( man recv 、 man send を参照)
独自のsend_all()
およびrecv_all()
を実装する必要があります。
bool send_all(int socket, void *buffer, size_t length)
{
char *ptr = (char*) buffer;
while (length > 0)
{
int i = send(socket, ptr, length);
if (i < 1) return false;
ptr += i;
length -= i;
}
return true;
}
次のガイドが役立つ場合があります Beejのネットワークプログラミングガイド
通常の問題。
_void excCommand(char *command)
{
if ( send(sock, command, strlen(command), 0) < 0)
ErrorWithSystemMessage("send() failed");
char replyMessage[BUFSIZE];
ssize_t numBytesRecv = 0;
do
{
numBytesRecv = recv(sock, replyMessage, BUFSIZE, 0);
if ( numBytesRecv < 0)
ErrorWithSystemMessage("recv() failed");
printf("%s\n", replyMessage);
_
無効。 numBytesRecv
はゼロである可能性があります。その場合、メッセージはまったくありません。それ以外の場合は、すでに否定についてテスト済みであり、メッセージの実際の長さを示すため、この時点では正でなければなりません。必ずしもnullで終了しているわけではありません。への変更:
_ if (numBytesRecv == 0)
break;
printf("%.*s\n", numBytesRecv, replyMessage);
_
その後:
_ memset(&replyMessage, 0, sizeof(replyMessage));
_
無意味です。削除する。
_ }
while (numBytesRecv > 0);
_
この時点で、_numBytesRecv < 0
_を確認し、perror()
またはそのフレンドの1つを呼び出す必要があります。
続行する必要があるかどうかにかかわらず、各send()の前に送信することを選択します。
だから私は最初に3つの定義を持っています
#define BUFFSIZE 1024
#define CONT "CONT"
#define DONE "DONE"
次に、私のデータを送信します
int send_to_socket(int sock, char *msg)
{
size_t len;
int ret[2];
len = strlen(msg);
ret[0] = send(sock, (len <= BUFFSIZE) ? DONE : CONT, 4, 0);
ret[1] = send(sock, msg, BUFFSIZE, 0);
if (ret[0] <= 0 || ret[1] <= 0)
{
perror("send_to_socket");
return (-1);
}
if (len > BUFFSIZE)
return (send_to_socket(sock, msg + BUFFSIZE));
return (1);
}
そしてそれを受け取るには:
char *recv_from_socket(int cs)
{
char state[5];
char buff[BUFFSIZE+1];
char *msg;
int ret[2];
msg = NULL;
while (42)
{
bzero(state, 5);
bzero(buff, BUFFSIZE+1);
ret[0] = recv(cs, state, 4, 0);
ret[1] = recv(cs, buff, BUFFSIZE, 0);
if (ret[0] <= 0 || ret[1] <= 0)
{
perror("recv_from_socket");
return (NULL);
}
// strfljoin() is selfmade
// join the string and free the left argument to prevent memory leaks.
// return fresh new string
msg = (msg) ? ft_strfljoin(msg, buff) : strdup(buff);
if (strncmp(state, DONE, 4) == 0)
break ;
i++;
}
return (msg);
}