C socket:recv并发送所有数据

Lor*_*que 9 c sockets client-server send recv

我想获得类似于此的行为:

  1. 服务器运行
  2. 客户端运行
  3. 客户端键入"帮助"或其他命令
  4. 服务器响应得当
  5. 去3

问题是,当我的函数excCommand("help")运行时,只接收并打印一个小文本.我的文本文件是这样的:

COMMAND HELP:

help - Display help
quit - Shutdown client
Run Code Online (Sandbox Code Playgroud)

仅打印命令帮助.另一个问题是,当我输入命令时,没有打印任何内容,并且在2命令客户端退出之后.特别是这件作品:

while (quit)
    {
        getLine("client> ", command, 10);
        if (strcmp(command, "quit") == 0)
            quit = 0;
        else
            excCommand(command);
    }
Run Code Online (Sandbox Code Playgroud)

这是服务器:

#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--;
        }

    }

}
Run Code Online (Sandbox Code Playgroud)

处理器:

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);
}
Run Code Online (Sandbox Code Playgroud)

这是我的客户:

#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);
}
Run Code Online (Sandbox Code Playgroud)

抱歉这么啰嗦

Jah*_*Jah 19

recv()send()功能不保证发送/ recv的所有数据(见男人的recv,人送)

您需要实现自己的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;
}
Run Code Online (Sandbox Code Playgroud)

以下指南可以帮助您Beej的网络编程指南

  • 这个send_all()函数不起作用.它应该将'buffer'声明为'char*'; 每当'i'为正时,它应该通过'i'递增'缓冲'; 如果'我'是否定的,当然应该完全停止. (4认同)
  • 您可以在每条消息之前添加消息的长度.和recv()固定的字节数表示消息大小的长度,然后调用recv(message_size) (3认同)
  • 整件事都是不必要的。`send()` 方法会阻塞,直到所有数据都传输完毕或发生错误。当然在阻塞模式下,但这就是这段代码所假设的。非阻塞实现必须使用`select()`来知道什么时候写下一个。 (2认同)