[英]Recv() function messing up other parts of my code
我正在嘗試使用客戶端服務器設置執行 cat|grep,工作方式如下:客戶端發送單詞以使用 grep 進行搜索,服務器執行 cat|grep,將結果發送到客戶端但recv()
function 似乎搞砸了用我的代碼。
有什么問題?
添加recv()
function 使我的代碼的其他部分不起作用,每個puts()
都可以工作,直到puts("test5");
這是我的代碼卡在執行中的地方,將recv()
function 作為注釋使代碼運行良好。
到目前為止,我沒有以任何方式使用我從客戶端發送的單詞,所以問題一定出在接收 function 本身,它沒有給出錯誤,並且當我打印我發送的內容時它工作正常。
這是相關的客戶端部分:
#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);
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;
}
幾點注意事項:
我知道在這段特定的代碼中,我沒有使用客戶端發送的單詞,因此為什么有些行是注釋,當我的問題得到解決時,我將實現這一點。
我正在使用popen()
因為我想返回catgrep()
的 output 。
我隔離了問題,而不是僅在包含recv()
function 時才發生。
當我使用recv()
時,正在打印我發送的單詞,因此 function 不會導致錯誤,但會弄亂其他部分。
更新:
正如評論中有人建議的那樣,我改變了接收客戶發送的單詞的方式,我現在使用以下內容:
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()");
}
仍然有同樣的問題和同樣的 output。
基本問題是你混淆了字符串和字節流——它們不是一回事。
在您的客戶端中,您發送一些數據:
char word[30];
fgets(word, 30, stdin);
if(send(sock, &word , 30, 0)<0)
這會將一行(包括換行符)讀入堆棧緩沖區的開頭,然后發送整個緩沖區,包括字符串結束后發生在其中的任何垃圾。 您可能不想要換行符,也許不想要 NUL 終止符,當然也不想要垃圾。
此外,對於短發送,您不會檢查 send 的返回值——在某些(非常罕見的)情況下,發送可能不會發送您請求的所有數據。
在閱讀方面,您不會檢查recv
的返回值來查看您獲得了多少字節,這可能與您的預期不同 - 無法保證 send 和 recv 調用之間會有 1:1 的對應關系聯系。 一個發送可能會被分解並拆分為多個接收,並且多個發送可能會將它們的數據組合並在一個接收中返回。 所以你總是需要檢查 recv 的返回值,看看你實際得到了多少字節。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.