【发布时间】:2021-08-17 08:44:37
【问题描述】:
我想实现一个 fork 并执行一个新进程的程序。然后,父进程将多次写入套接字,子进程(执行)将从套接字读取写入发送的全部数据。问题是有时当我运行程序时,子进程读取 4501 次或更多并打印垃圾,而父进程只写入 4500。 这不会一直发生,所以我怀疑某处可能有一个统一变量。
父进程:
#include <stdio.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <unistd.h>
#include <stdlib.h>
#include <ctype.h>
#include <signal.h>
#include <string.h>
typedef char * String;
void perror_exit(char *message);
int getSocketWrite(int portWrite){
struct hostent *remWrite;
struct sockaddr *serverptrWrite = NULL;
struct sockaddr_in serverWrite;
int sockWrite;
serverptrWrite = (struct sockaddr*)&serverWrite;
if ((sockWrite = socket(AF_INET, SOCK_STREAM, 0)) < 0)
perror_exit("socket");
if (setsockopt(sockWrite, SOL_SOCKET, SO_REUSEADDR, &(int){1}, sizeof(int)) < 0) //To reuse port if program exits.
perror("setsockopt(SO_REUSEADDR) failed");
char hostname[256];
gethostname(hostname, 256);
if ((remWrite = gethostbyname(hostname)) == NULL) {
herror("gethostbyname");
exit(1);
}
serverWrite.sin_family = AF_INET;
memcpy(&serverWrite.sin_addr, remWrite->h_addr, remWrite->h_length);
serverWrite.sin_port = htons(portWrite);
while (connect(sockWrite, serverptrWrite, sizeof(serverWrite)) < 0);
return sockWrite;
}
void main(int argc, char *argv[]) {
int portWrite, sockWrite, i;
int buffsize = 256;
char buf[buffsize];
struct sockaddr_in serverWrite;
struct sockaddr *serverptrWrite = NULL;
struct hostent *remWrite = NULL;
portWrite = 8080;
pid_t pid = fork();
if(pid == 0){
execl("./server", "server");
exit(1);
}
else if(pid < 0){
perror("error in fork");
}
sockWrite = getSocketWrite(portWrite);
printf("Connecting to %s port %d\n", "Lenovo", portWrite);
for(int i = 0; i < 4500; i++){
memset(buf, 0, buffsize);
strcpy(buf,"Test");
write(sockWrite, buf, buffsize);
}
close(sockWrite);
}
void perror_exit(char *message){
perror(message);
exit(EXIT_FAILURE);
}
server.c:
#include <stdio.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <unistd.h>
#include <stdlib.h>
#include <ctype.h>
#include <signal.h>
#include <string.h>
typedef char * String;
void perror_exit(char *message);
int getSocketRead(int portRead){
struct sockaddr_in serverRead;
struct sockaddr *serverptrRead;
int sockRead;
serverptrRead = (struct sockaddr*)&serverRead;
if ((sockRead = socket(AF_INET, SOCK_STREAM, 0)) < 0){
perror("socket");
exit(1);
}
if (setsockopt(sockRead, SOL_SOCKET, SO_REUSEADDR, &(int){1}, sizeof(int)) < 0) //To reuse port if program exits.
perror("setsockopt(SO_REUSEADDR) failed");
serverRead.sin_family = AF_INET;
serverRead.sin_addr.s_addr = htonl(INADDR_ANY);
serverRead.sin_port = htons(portRead);
if (bind(sockRead, serverptrRead, sizeof(serverRead)) < 0){
perror("bind");
exit(1);
}
if (listen(sockRead, 5) < 0) {
perror("listen");
exit(1);
}
printf("Listening for connections to port %d\n", portRead);
return sockRead;
}
int main(int argc, char *argv[]) {
int buffsize = 256;
char buffer[buffsize];
int portRead, sockRead, newsock;
struct sockaddr_in serverRead, clientRead;
socklen_t clientlen = 0;
struct sockaddr *serverptrRead = NULL;
struct sockaddr *clientptrRead = NULL;
// //////////////////////////////////////////////////////////////////////////////////////////
portRead = 8080;
sockRead = getSocketRead(portRead);
if ((newsock = accept(sockRead, clientptrRead, &clientlen)) < 0) {
perror("accept");
exit(1);
}
int count = 0;
int bytes = 0;
memset(buffer, 0, buffsize);
while ((bytes = read(newsock, buffer, buffsize)) > 0){
count++;
buffer[bytes] = '\0';
printf("%s %d bytes\n", buffer, bytes);
}
close(sockRead);
printf("Count = %d\n",count);
}
void perror_exit(char *message){
perror(message);
exit(EXIT_FAILURE);
}
我在运行程序的 5 次中大约有 1 次出现错误。 奇怪的是,当我每 500 次使用 sleep(1) 时,我写了大约 该程序似乎运行良好。
【问题讨论】:
-
"子进程读取 4501 次或更多"。这是完全不足为奇的行为。对于 TCP 等基于流的协议,每个
read不能保证准确接收使用单个write发送的内容。 -
reader读取的总字节数是否等于writer写入的总字节数?
-
我怎样才能得到每一次写入的确切信息?有没有可能我做不到?
-
No 当我得到错误读取返回随机字节数但如果我得到错误字节总是低于 buffsize。
标签: c sockets system-calls