接收函数将我的代码的其他部分弄乱了

问题描述 投票:0回答:1

我正在尝试使用客户端服务器设置执行cat | grep,其工作方式如下:客户端使用grep发送单词以进行搜索,服务器执行cat | grep,将结果发送给客户端,但是recv()函数似乎是弄乱我的代码。

这里是相关的客户部分:

#include <stdio.h> 
#include <sys/socket.h> 
#include <arpa/inet.h> 
#include <unistd.h> 
#include <string.h> 
#include <stdlib.h>
#include<errno.h>

#define PORT 8080

int main(int argc, char const *argv[]) 
{ 
    int sock = 0, valread; 
    struct sockaddr_in serv_addr; 
    int buffer[1024];
    char buffer2[1024]={0};
    if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) 
    { 
        printf("\n Socket creation error \n"); 
        return -1; 
     } 

    serv_addr.sin_family = AF_INET; 
    serv_addr.sin_port = htons(PORT);        

    if(inet_pton(AF_INET, "127.0.0.1", &serv_addr.sin_addr)<=0)  
    { 
        perror("Invalid address \n"); 
        return -1; 
    } 

    if (connect(sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) 
    { 
        perror("Connection Failed \n"); 
        return -1; 
    } 

    int i, array[argc], countsize=0;
    if(argc>=2)
    {
        for(i=1; i<argc; i++)
        {
            int number=atoi(argv[i]);
            array[i-1]=number;
            countsize++;
        }

        if(send(sock, array, countsize*sizeof(int), 0)<0)
        {
            printf("Error in send! %s\n", strerror(errno));
           return -1; 
        }

        if(argc>=2)
        {
             int i=0;
             for(int i=0; i<argc; i++) 
            {
                if(atoi(argv[i])==6)
                {
                    puts("Please enter the name/word you want to search for in the history file: ");
                    char word[30];
                    fgets(word, 30, stdin); 
                    if(send(sock, &word , 30, 0)<0)
                        printf("Error in send! %s\n", strerror(errno));

                    valread = read( sock , buffer2, 1024); 
                    puts("The result cat|grep is:");
                    printf("%s\n", buffer2);
                }
            }  
        }
    }      
    return 0; 
} 

这是服务器的主要方法:

#include <stdio.h> 
#include <unistd.h> 
#include <sys/socket.h> 
#include <stdlib.h> 
#include <netinet/in.h> 
#include <string.h> 
#include<errno.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdbool.h>
#include <sys/wait.h>
#include<time.h> 
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>
#include <pthread.h>
#include <arpa/inet.h> 

#define PORT 8080
void *catgrep(void *);

int main() 
{ 
    int server_fd, new_socket;
    struct sockaddr_in address; 
    int opt = 1; 
    int addrlen = sizeof(address); 
    char buffer2[1024]={0};

    if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0) 
    { 
        perror("socket failed"); 
        exit(EXIT_FAILURE); 
    }        

    if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR , &opt, sizeof(opt))) 
    { 
        perror("setsockopt"); 
        exit(EXIT_FAILURE); 
    } 
    address.sin_family = AF_INET; 
    address.sin_addr.s_addr = INADDR_ANY; 
    address.sin_port = htons( PORT );       

    if (bind(server_fd, (struct sockaddr *)&address, sizeof(address))<0) 
    { 
        perror("bind failed"); 
        exit(EXIT_FAILURE); 
    } 

    while (1)
    {
        if (listen(server_fd, 20) < 0) 
        { 
            perror("listen"); 
            exit(EXIT_FAILURE); 
        } 
        if ((new_socket = accept(server_fd, (struct sockaddr *)&address,(socklen_t*)&addrlen))<0) 
        { 
            perror("accept"); 
            exit(EXIT_FAILURE); 
        } 

        int arguments[10]={0};
        int n = recv(new_socket, arguments ,1024*sizeof(int),0);
    int j;

        int argumentsize=n/sizeof(int);
        for(j=0; j<argumentsize;j++)
        {
            if(arguments[j]==6)
            {
                pthread_t th5;
                pthread_attr_t attr5;
                pthread_attr_init(&attr5);

                if(pthread_create(&th5,&attr5, catgrep,&new_socket)!=0)
                {
                    printf("Error in pthread_create %s\n", strerror(errno));
                    return -1; 
                }
                pthread_join(th5, NULL);
               return -1; 
           }
        } 
        close(new_socket);
    }
    close(server_fd);
    return 1;
}

这是我的catgrep()方法:

void *catgrep(void * param)
{
    int *sock = (int*) param;
    int new_sock = *sock;

    int fd[2];
    pipe(fd);
    pid_t pid = fork(); 
    char word[30];
    recv(new_sock, word ,30, 0); //when I put this line code 
    starts messing up. 
    puts(word);
    //char command[1024];
    //sprintf(command,"%s %s","grep -w",word);

    if(pid==0)
    {
        close(1);
        dup(fd[1]);
        close(fd[0]);
        close(fd[1]);
        char *cat_args[] = {"/bin/cat", "GameData.txt", NULL};
        if(execv(cat_args[0], cat_args)<0)
        {
            printf("Error in execv! %s\n", strerror(errno));
        }
       exit(0);
    }

    if(pid > 0)
    {
        close(0);
        dup(fd[0]);
        close (fd[1]);
        close(fd[0]);

        puts("test2");
        FILE *fp2;
        if ((fp2 = popen("grep -w tries", "r")) == NULL)
        {
            perror("popen failed");
            return NULL;
        }
        puts("test3");
        size_t str_size = 1024;
        char *stringts2 = malloc(str_size);
        if (!stringts2)
        {
            perror("stringts allocation failed");
            return NULL;
        }
        puts("test4");

        stringts2[0] = '\0';
        char buf[128];
        size_t n;
        puts("test5"); //when I use recv() code get stuck here, 
        prints test 5 and everything before then gets stuck

        while ((n = fread(buf, 1, sizeof(buf) - 1, fp2)) > 0)
        {
            puts("test10");
            buf[n] = '\0';
            size_t capacity = str_size - strlen(stringts2) - 1;
            while (n > capacity)
            {
                str_size *= 2;
                stringts2 = realloc(stringts2, str_size);
                if (!stringts2)
                {
                    perror("stringts realloation failed");
                    return NULL;
                }
                capacity = str_size - strlen(stringts2) - 1;
            }
            strcat(stringts2, buf);
        }

        puts("test6");

        if (pclose(fp2) != 0)
        {
            perror("pclose failed");
            return NULL;
        }
        puts("test7");

        if(send(new_sock, stringts2, 10000, 0)<0)
        {
            printf("Error in send! %s\n", strerror(errno));
        }
    }
    return NULL;
}

一些注意事项:

我知道在这段特定的代码中,我没有使用客户端发送的单词,因此为什么有些行用作注释,所以当问题解决后,我将实现这一点。

我正在使用popen(),因为我想返回catgrep()的输出。

我隔离了问题,并且不是仅当我包含recv()函数时才发生。

使用recv()时,正在打印的单词正在打印,因此该功能不会引起错误,但会弄乱其他部分。

c recv
1个回答
1
投票

基本问题是,您在混淆字符串和字节流-它们不是同一回事。

在您的客户端中,您通过以下方式发送了一些数据:

        char word[30];
        fgets(word, 30, stdin); 
        if(send(sock, &word , 30, 0)<0)

这将在堆栈缓冲区的开头读取一行(包括换行符),然后发送entire缓冲区,包括字符串末尾出现的任何垃圾。您可能不需要换行符,也许不需要NUL终止符,当然也不需要垃圾。

此外,对于短发送,您不检查send的返回值-在某些(非常罕见)的情况下,发送可能不会发送您请求的所有数据。

在阅读方面,您无需检查recv的返回值即可查看获得的字节数,这可能与您期望的字节数有所不同-没有保证发送和发送之间将存在1:1对应关系recv调用连接。一个发送可能会分解并拆分为多个recv,而几个发送可能会将其数据合并并在一个recv中返回。因此,您始终需要检查recv的返回值以查看实际获得的字节数。

© www.soinside.com 2019 - 2024. All rights reserved.