交流电插座:recv和send所有数据 [英] C socket: recv and send all data

查看:149
本文介绍了交流电插座:recv和send所有数据的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想获得一个类似的行为:


  1. 服务器运行

  2. 客户端运行

  3. 客户端类型,如帮助或其他
  4. 命令
  5. 服务器作适当的反应

  6. 去3

问题是,当我的功能excCommand(帮助)运行只是一个小的文本被接收并打印。
我的文本文件是这样的:

 命令帮助:帮助 - 显示帮助
退出 - 关闭客户端

只是命令的帮助打印。
另一个问题是,当我键入命令没有打印后2命令的客户端退出。
这是特别的片

 而(退出)
    {
        函数getline(客户机gt;中,命令,10);
        如果(STRCMP(指挥,跳槽)== 0)
            退出= 0;
        其他
            excCommand(命令);
    }

这是服务器:

 的#include<&stdio.h中GT;
#包括LT&;&stdlib.h中GT;
#包括LT&;&string.h中GT;
#包括LT&;&unistd.h中GT;#包括COMMON.HINT主(INT ARGC,CHAR *的argv [])
{
    如果(的argc!= 2)
        ErrorWithUserMessage(参数(S),<服务器端口>);    字符*服务=的argv [1];    INT servSock = SetupTCPServerSocket(服务);
    如果(servSock℃,)
        ErrorWithUserMessage(SetupTCPServerSocket()失败,无法确定);    unsigned int类型childProcessCount = 0;
    而(1)
    {
        INT clntSock = AcceptTCPConnection(servSock);        将为pid_t进程ID = fork()的;
        如果(进程ID℃,)
            ErrorWithSystemMessage(叉()失败);
        否则,如果(进程ID == 0)
        {
            关闭(servSock);
            HandleTCPClient(clntSock);
            出口(EXIT_SUCCESS);
        }        输出(与子进程数:%d \\ n,进程ID);
        关闭(clntSock);
        childProcessCount ++;        //清理僵尸
        而(childProcessCount)
        {
            进程ID = waitpid函数((将为pid_t) - 1,NULL,WNOHANG);
            如果(进程ID℃,)
                ErrorWithSystemMessage(waitpid函数()失败);
            否则,如果(进程ID == 0)
                打破;
            其他
                childProcessCount--;
        }    }}

处理器:

 无效HandleTCPClient(INT clntSock)
{
    字符缓冲区[BUFSIZE];
    ssiz​​e_t供numBytesRcvd =的recv(clntSock,缓冲器,BUFSIZE,0);
    缓冲[numBytesRcvd] ='\\ 0';
    如果(numBytesRcvd℃,)
        ErrorWithSystemMessage(的recv()失败);
    如果(STRCMP(缓冲,帮助)== 0)
    {
        FILE *计划生育=的fopen(的help.txt,R);
        如果(FP)
        {
            焦线[128];
            而(与fgets(线,的sizeof(线),FP)!= NULL)
            {
                如果(发送(clntSock,行,的sizeof(线),0)℃下)
                    ErrorWithSystemMessage(寄()失败);
            }
            FCLOSE(FP);
        }
    }    关闭(clntSock);
}

这是我的客户:

 的#include<&stdio.h中GT;
#包括LT&;&stdlib.h中GT;
#包括LT&;&string.h中GT;
#包括LT&;&unistd.h中GT;#包括LT&; SYS / types.h中>
#包括LT&; SYS / socket.h中>#包括COMMON.HINT袜子;无效函数getline(字符*消息,字符* buf中,诠释MAXLEN)
{
    的printf(%S,消息);
    与fgets(BUF,MAXLEN,标准输入);
    的buf [strlen的(BUF) - 1] = 0;
}无效excCommand(字符*命令)
{
    如果(发送(袜子,命令,strlen的(命令),0)℃下)
        ErrorWithSystemMessage(寄()失败);    焦炭replyMessage [BUFSIZE];
    ssiz​​e_t供numBytesRecv = 0;
    做
    {
        numBytesRecv =的recv(袜子,replyMessage,BUFSIZE,0);
        如果(numBytesRecv℃,)
            ErrorWithSystemMessage(的recv()失败);
        的printf(%S \\ n,replyMessage);
        memset的(安培; replyMessage,0,sizeof的(replyMessage));    }
    而(numBytesRecv大于0);
}无效PrintFile(为const char *文件名)
{
    FILE * FP;
    FP = FOPEN(文件名,R);
    如果(FP)
    {
        焦线[128];
        而(与fgets(线,的sizeof(线),FP)!= NULL)
            的fputs(线,标准输出);
        的fputs(\\ n,标准输出);
        FCLOSE(FP);
    }
}INT主(INT ARGC,CHAR *的argv [])
{
    INT退出= 1;
    字符命令[10];    如果(argc个2 ||的argc→3)
    {
        ErrorWithUserMessage(参数(S),<服务器地址><服务器端口>);
    }    字符*服务器=的argv [1];
    字符*服务=的argv [2];    袜子= SetupTCPClientSocket(服务器,服务);
    如果(袜子℃,)
        ErrorWithUserMessage(SetupTCPClientSocket()失败,无法连接);    的printf(连接建立\\ n \\ n!);    PrintFile(menu.txt);
    excCommand(帮助);    而(退出)
    {
        函数getline(客户机gt;中,命令,10);
        如果(STRCMP(指挥,跳槽)== 0)
            退出= 0;
        其他
            excCommand(命令);
    }    的fputs(\\ n,标准输出);
    关闭(袜子);
    出口(EXIT_SUCCESS);
}

抱歉这么啰嗦

解决方案

的recv()发送()函数不保证发送/ recv的所有数据(见人的recv ,的人送上

您需要实现自己的 send_all() recv_all(),像

 布尔send_all(INT插座,无效*缓冲区,为size_t长度)
{
    字符* PTR =(字符*)缓冲;
    而(长度大于0)
    {
        INT I =发送(插座,PTR,长度);
        如果(I< 1)返回false;
        PTR + =我;
        长度 - =我;
    }
    返回true;
}

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

I would like to obtain a behavior similar to this:

  1. Server run
  2. Client run
  3. Client type a command like "help" or other
  4. Server responds appropriately
  5. go to 3

The problem is that when my function excCommand("help") run just a little text is received and printed. My text file is this:

COMMAND HELP:

help - Display help
quit - Shutdown client

only COMMAND HELP is printed. Another problem is that when i type a command nothing is printed and after 2 command client exit. This is the piece in particular:

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

This is the server:

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

    }

}

Handler:

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

and this is my client:

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

sorry for being so long-winded

解决方案

The recv() and send() functions do not guarantee to send/recv all data (see man recv, man send)

You need to implement your own send_all() and recv_all(), something like

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

The following guide may help you Beej's Guide to Network Programming

这篇关于交流电插座:recv和send所有数据的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆