Tôi đang làm việc trên một ứng dụng có chứa một số ổ cắm máy chủ mà mỗi máy chủ chạy trong một chuỗi duy nhất.
Tiện ích bên ngoài (tập lệnh) được gọi bởi một trong các chủ đề. Kịch bản lệnh này gọi một tiện ích (máy khách) gửi một thông điệp đến một trong các ổ cắm máy chủ.socket() trả về 0 trong ứng dụng máy chủ ứng dụng khách C
Ban đầu, tôi đang sử dụng system()
để thực thi tập lệnh bên ngoài này, nhưng chúng tôi không thể sử dụng vì chúng tôi phải đảm bảo rằng các cổng máy chủ đã được đóng trong đứa trẻ được chia nhỏ để thực thi tập lệnh bên ngoài.
Tôi hiện gọi số fork()
và execvp()
. Tôi fork()
và sau đó trong đứa trẻ tôi đóng tất cả các ổ cắm máy chủ và sau đó gọi execvp()
để thực thi kịch bản.
Bây giờ, tất cả đều hoạt động tốt. Vấn đề là đôi khi kịch bản báo cáo lỗi cho ứng dụng máy chủ. Kịch bản lệnh gửi các lỗi này bằng cách gọi một ứng dụng (client) khác mở một socket TCP và gửi dữ liệu thích hợp. Vấn đề của tôi là ứng dụng khách nhận được một giá trị là 0
được trả về bởi cuộc gọi hệ thống socket()
.
LƯU Ý: CHỈ này xảy ra khi ứng dụng tập lệnh/ứng dụng khách được gọi bằng hàm forkExec() của tôi. Nếu ứng dụng tập lệnh/ứng dụng khách được gọi theo cách thủ công thì cuộc gọi socket()
hoạt động phù hợp và mọi thứ hoạt động tốt.
Dựa trên thông tin đó, tôi nghi ngờ có gì đó trong ngã ba() mã execvp() của tôi bên dưới ... Bất kỳ ý tưởng nào?
void forkExec()
{
int stat;
stat = fork();
if (stat < 0)
{
printf("Error forking child: %s", strerror(errno));
}
else if (stat == 0)
{
char *progArgs[3];
/*
* First, close the file descriptors that the child
* shouldn't keep open
*/
close(ServerFd);
close(XMLSocket);
close(ClientFd);
close(EventSocket);
close(monitorSocket);
/* build the arguments for script */
progArgs[0] = calloc(1, strlen("/path_to_script")+1);
strcpy(progArgs[0], "/path_to_script");
progArgs[1] = calloc(1, strlen(arg)+1);
strcpy(progArgs[1], arg);
progArgs[2] = NULL; /* Array of args must be NULL terminated for execvp() */
/* launch the script */
stat = execvp(progArgs[0], progArgs);
if (stat != 0)
{
printf("Error executing script: '%s' '%s' : %s", progArgs[0], progArgs[1], strerror(errno));
}
free(progArgs[0]);
free(progArgs[1]);
exit(0);
}
return;
}
Khách hàng mã ứng dụng:
static int connectToServer(void)
{
int socketFD = 0;
int status;
struct sockaddr_in address;
struct hostent* hostAddr = gethostbyname("localhost");
socketFD = socket(PF_INET, SOCK_STREAM, 0);
Cuộc gọi lợi nhuận trên 0.
if (socketFD < 0)
{
fprintf(stderr, "%s-%d: Failed to create socket: %s",
__func__, __LINE__, strerror(errno));
return (-1);
}
memset(&address, 0, sizeof(struct sockaddr));
address.sin_family = AF_INET;
memcpy(&(address.sin_addr.s_addr), hostAddr->h_addr, hostAddr->h_length);
address.sin_port = htons(POLLING_SERVER_PORT);
status = connect(socketFD, (struct sockaddr *)&address, sizeof(address));
if (status < 0)
{
if (errno != ECONNREFUSED)
{
fprintf(stderr, "%s-%d: Failed to connect to server socket: %s",
__func__, __LINE__, strerror(errno));
}
else
{
fprintf(stderr, "%s-%d: Server not yet available...%s",
__func__, __LINE__, strerror(errno));
close(socketFD);
socketFD = 0;
}
}
return socketFD;
}
FYI
Hệ điều hành: Linux
Arch: ARM32
Kernel: 2.6.26
Bạn có thể đăng mã gọi socket() không? – abc
Không có ý tưởng gì đang xảy ra với ổ cắm của bạn. Có lẽ đó là trợ giúp cho bạn nếu tôi chỉ ra rằng bạn có thể khai báo các đối số của bạn đơn giản hơn nhiều: const char * progArgs [] = {"/ path_to_script", arg, NULL}; - Không cần phải phân bổ và sao chép, tất cả những gì bạn cần là một mảng với các con trỏ thích hợp tại thời điểm bạn gọi execvp. – VoidPointer