[英]How do i fix my pipe in linux socket program?
我包含了我的一些代碼,當我運行我的程序(服務器)時,一切正常,除了 pipe 我真的不確定問題出在哪里,output 總是打印 0 並且兩個錯誤消息都被打印出來。(點代表塊我省略了代碼)首先程序與客戶端建立連接,然后開始通信,在通信結束時子進程中的 pipe 假設將變量小時發送到父進程中的 pipe。
#define PORT 4444
#define BUF_SIZE 2000
#define CLADDR_LEN 100
void func(int subor,int rychlost,int *h,int *m,int *s){
int hours,minutes,seconds,inputSecond;
int remainingSeconds;
int secondsInHour = 60 * 60;
int secondsInMinute = 60;
subor *= 8000;
rychlost *= 1000;
inputSecond = subor/rychlost;
hours = (inputSecond/secondsInHour);
remainingSeconds = inputSecond - (hours * secondsInHour);
minutes = remainingSeconds/secondsInMinute;
remainingSeconds = remainingSeconds - (minutes*secondsInMinute);
seconds = remainingSeconds;
*h=hours;
*m=minutes;
*s=seconds;
}
void main() {
struct sockaddr_in addr, cl_addr;
int sockfd, len, ret, newsockfd,fileSize,speed;
char buffer[BUF_SIZE]="Type 'start' or 'exit'\n";
pid_t childpid;
int hours,minutes,seconds;
int fd[2];
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0) {
printf("Error creating socket!\n");
exit(1);
}
printf("Socket created...\n");
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = INADDR_ANY;
addr.sin_port = PORT;
ret = bind(sockfd, (struct sockaddr *) &addr, sizeof(addr));
if (ret < 0) {
printf("Error binding!\n");
exit(1);
}
printf("Binding done...\n");
printf("Waiting for a connection...\n");
listen(sockfd, 5);
for (;;) {
len = sizeof(cl_addr);
newsockfd = accept(sockfd, (struct sockaddr *) &cl_addr, &len);
if (newsockfd < 0) {
printf("Error accepting connection!\n");
exit(1);
}
printf("Connection accepted...\n");
if ((childpid = fork()) == 0) {
close(fd[0]);
close(sockfd);
ret = send(newsockfd, buffer, BUF_SIZE, 0);
if (ret < 0) {
printf("Error sending data!\n");
exit(1);
}
for (;;) {
memset(buffer, 0, BUF_SIZE);
ret = recv(newsockfd, buffer, BUF_SIZE, 0);
if(ret < 0) {
printf("Error receiving data!\n");
exit(1);
}
if (strcmp(buffer, "start\n") == 0) {
ret = send(newsockfd, "Type size of file in [Mb]\n", BUF_SIZE, 0);
if (ret < 0) {
printf("Error sending data!\n");
exit(1);
}
ret = recv(newsockfd, buffer, BUF_SIZE, 0);
if(ret < 0) {
printf("Error receiving data!\n");
exit(1);
}
fileSize = atoi(buffer);
ret = send(newsockfd, "Type Speed of internet in [MB]\n", BUF_SIZE, 0);
if (ret < 0) {
printf("Error sending data!\n");
exit(1);
}
ret = recv(newsockfd, buffer, BUF_SIZE, 0);
if(ret < 0) {
printf("Error receiving data!\n");
exit(1);
}
speed = atoi(buffer);
func(fileSize,speed,&hours,&minutes,&seconds);
buffer[BUF_SIZE] = sprintf(buffer,"Upload bude trvat %d:%d:%d\n",hours,minutes,seconds);
if((write(fd[1], &hours,sizeof(int))) == -1){ \\problem is here
printf("write error\n");
}
close(fd[1]);
ret = send(newsockfd, buffer, BUF_SIZE, 0);
if (ret < 0) {
printf("Error sending data!\n");
exit(1);
}
exit(0);
}
}
}else{
wait();
close(fd[1]);
int fin;
if((read(fd[0], &fin, sizeof(int))) == -1){ \\problem is here
printf("read error\n");
}
printf("%d\n",fin);
close(fd[0]);
}
close(newsockfd);
}
}
好吧,在解決了您發送的代碼中的一些問題之后,我想我已經讓您的代碼運行了:
$ netstat -p -l | grep pru28763
tcp 0 0 0.0.0.0:23569 0.0.0.0:* ESCUCHAR 46607/pru28763
$ _
您的進程實際上正在偵聽,但不在端口4444
中,而是在端口46607
中。 這意味着您沒有通過調用htons()
宏將端口號轉換為網絡字節順序。 你需要這樣做。
我將向您發送一個包含對您的代碼所做的所有更正的差異,以使其運行,但您沒有初始化數組fd[]
並且,因為我不知道您想如何使用它(沒有在您發布的代碼中調用pipe(2)
)我無法進一步幫助您:
diff --git a/pru28763.c b/pru28763.c
index 78792e9..a6b7c7d 100644
--- a/pru28763.c
+++ b/pru28763.c
@@ -57,7 +57,7 @@ void main() {
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = INADDR_ANY;
- addr.sin_port = PORT;
+ addr.sin_port = htons(PORT);
ret = bind(sockfd, (struct sockaddr *) &addr, sizeof(addr));
if (ret < 0) {
@@ -84,7 +84,7 @@ void main() {
close(sockfd);
- ret = send(newsockfd, buffer, BUF_SIZE, 0);
+ ret = send(newsockfd, buffer, strlen(buffer), 0);
if (ret < 0) {
printf("Error sending data!\n");
exit(1);
@@ -102,25 +102,32 @@ void main() {
}
- if (strcmp(buffer, "start\n") == 0) {
+ char *startmsg = "start\n";
+ if (strncmp(buffer, startmsg, strlen(startmsg)) == 0) {
- ret = send(newsockfd, "Type size of file in [Mb]\n", BUF_SIZE, 0);
+ char *msg = "Type size of file in [Mb]\n";
+ ret = send(newsockfd, msg, strlen(msg), 0);
if (ret < 0) {
printf("Error sending data!\n");
exit(1);
}
- ret = recv(newsockfd, buffer, BUF_SIZE, 0);
+ /* to allow for a \0 that must be put at the end of what
+ * is received */
+ ret = recv(newsockfd, buffer, BUF_SIZE - 1, 0);
if(ret < 0) {
printf("Error receiving data!\n");
exit(1);
}
+
+ buffer[ret] = '\0';
fileSize = atoi(buffer);
- ret = send(newsockfd, "Type Speed of internet in [MB]\n",
-BUF_SIZE, 0);
+ msg = "Type Speed of internet in [MB]\n";
+
+ ret = send(newsockfd, msg, strlen(msg), 0);
if (ret < 0) {
printf("Error sending data!\n");
exit(1);
@@ -131,6 +138,10 @@ BUF_SIZE, 0);
printf("Error receiving data!\n");
exit(1);
}
+
+ /* again, you must end a buffer read with a \0 if you
+ * want it to be checked with string routines */
+ buffer[ret] = '\0';
speed = atoi(buffer);
@@ -139,6 +150,7 @@ BUF_SIZE, 0);
buffer[BUF_SIZE] = sprintf(buffer,"Upload bude trvat %d:%d:%d\n",hours,minutes,seconds);
+ /* fd array has not been initialized, no pipe(2) call shown */
if((write(fd[1], &hours, sizeof(int))) == -1){ /*problem is here */
printf("write error\n");
}
@@ -162,6 +174,8 @@ BUF_SIZE, 0);
int fin;
+ /* no initialization of array fd, no pipe call shown in the snippet
+ * sent */
if((read(fd[0], &fin, sizeof(int))) == -1){ /*problem is here */
printf("read error\n");
}
順便說一句,問題不在於您標記為候選人的任何一個地方,而是因為您堅持使用send(2)
發送文本消息而不指定數據長度,因此您發送完整的緩沖區,盡管內容可能有。 此外,您讀取了一個完整的緩沖區,然后使用strcmp(3)
檢查字符串。 客戶端可以緩沖它的 output,並向您發送一個完整的 1500 字節數據塊,以“start\n”開頭,這將導致無法識別起始子序列。
我放棄了你的代碼,它需要我花費一個多小時的時間,這不是我們都想要的。 我很抱歉。 嘗試修復(並理解)我對您的代碼所做的所有修改。 下一次,至少,將其格式化為至少可讀。 縮進是理解程序邏輯的基礎,你沒有花足夠的時間讓閱讀你的代碼的人更容易理解。 請閱讀如何創建一個最小的、可重現的示例以了解如何將代碼發送到此論壇。
分叉子進程后,connect() 丟失。
您已使用newsockfd從子進程發送數據。 newsockfd是接受系統調用的返回值。 這是錯誤的。
閱讀: https://www.geeksforgeeks.org/tcp-server-client-implementation-in-c/
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.