简体   繁体   English

Recv() function 弄乱了我代码的其他部分

[英]Recv() function messing up other parts of my code

I am trying to execute cat|grep using a client server set-up, works as follows: client sends word to search for using grep, server executes cat|grep, sends results to client but the recv() function seems to be messing up with my code.我正在尝试使用客户端服务器设置执行 cat|grep,工作方式如下:客户端发送单词以使用 grep 进行搜索,服务器执行 cat|grep,将结果发送到客户端但recv() function 似乎搞砸了用我的代码。

What's the problem?有什么问题?

Adding the recv() function makes other parts of my code not working, every puts() works until puts("test5");添加recv() function 使我的代码的其他部分不起作用,每个puts()都可以工作,直到puts("test5"); which is where my code is stuck in the execution, putting the recv() function as a comment makes the code run fine.这是我的代码卡在执行中的地方,将recv() function 作为注释使代码运行良好。

Till now I am not using the word I send from the client in any way so the problem must be with the receive function itself, it's not giving an error and when I print the content I send it works fine.到目前为止,我没有以任何方式使用我从客户端发送的单词,所以问题一定出在接收 function 本身,它没有给出错误,并且当我打印我发送的内容时它工作正常。

Here is the relevant client part:这是相关的客户端部分:

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

Here is the server's main method:这是服务器的主要方法:

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

Here is my catgrep() method:这是我的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);

    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 the recv() program gets stuck here. 

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

Few notes:几点注意事项:

I am aware that in this particular piece of code I am not using the word sent by the client, hence why some lines are as comments, I will implement this when my problem gets fixed.我知道在这段特定的代码中,我没有使用客户端发送的单词,因此为什么有些行是注释,当我的问题得到解决时,我将实现这一点。

I am using popen() as I want to return the output of catgrep() .我正在使用popen()因为我想返回catgrep()的 output 。

I isolated the problem and not it's only happening when I include the recv() function.我隔离了问题,而不是仅在包含recv() function 时才发生。

The word I am sending is being printed when I use recv() so the function isn't causing errors but it's messing up other parts.当我使用recv()时,正在打印我发送的单词,因此 function 不会导致错误,但会弄乱其他部分。

UPDATE:更新:

As suggested by someone in the comments I changed the way I receive the word sent by my client, I am now using the following:正如评论中有人建议的那样,我改变了接收客户发送的单词的方式,我现在使用以下内容:

int count = 0;
int total = 0;

while ((count = recv(new_sock, &word[total], sizeof word - count, 0)) > 0)
{
    total=total+count;
}
if (count==-1)
{
    perror("error in recv()");
}

Still having the same problem and same output.仍然有同样的问题和同样的 output。

The basic problem is that you are confusing strings and byte streams -- they're not the same thing.基本问题是你混淆了字符串和字节流——它们不是一回事。

In your client, you send some data with:在您的客户端中,您发送一些数据:

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

This will read a line (including a newline) into the beginning of an on-stack buffer, and then send the entire buffer, including whatever garbage happens to be in it after the end of the string.这会将一行(包括换行符)读入堆栈缓冲区的开头,然后发送整个缓冲区,包括字符串结束后发生在其中的任何垃圾。 You probably don't want the newline, maybe don't want the NUL terminator, and certainly don't want the garbage.您可能不想要换行符,也许不想要 NUL 终止符,当然也不想要垃圾。

In addition, you don't check the return value of send for a short send -- in some (admittedly rare) situations, a send might not send all the data you request.此外,对于短发送,您不会检查 send 的返回值——在某些(非常罕见的)情况下,发送可能不会发送您请求的所有数据。

On the reading side you don't check the return value of recv to see how many bytes you got, which may be different from what you expect -- there's no guarentee that there will be 1:1 correspondence between send and recv calls on a connection.在阅读方面,您不会检查recv的返回值来查看您获得了多少字节,这可能与您的预期不同 - 无法保证 send 和 recv 调用之间会有 1:1 的对应关系联系。 One send might get broken up and split across multiple recvs, and several sends might have their data combined and returned in one recv.一个发送可能会被分解并拆分为多个接收,并且多个发送可能会将它们的数据组合并在一个接收中返回。 So you always need to check the return value of recv to see how many bytes you actually got.所以你总是需要检查 recv 的返回值,看看你实际得到了多少字节。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM