【发布时间】:2014-11-24 14:59:42
【问题描述】:
我正在实现一个简单的 TCP process-per-client 并发回显服务器。服务器无法从第一个客户端读取字符串。但是,对于其他客户端,服务器会正确回显字符串。我觉得阅读字符串可能有问题;服务器端无法检测到 EOF。我尝试使用 send()/recv() 而不是 read()/write() 没有成功。我还尝试了其他从标准输入读取字符串的函数——即 fgets()、scanf() 等。
这个问题的可能原因是什么;即服务器无法仅从第一个客户端读取?
服务端和客户端的代码如下 -
// server.c
#include <signal.h>
#include <sys/wait.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <string.h>
#define BUF_SIZE 4096
#define MAXPENDING 256
static void zombieReaper(int sig)
{
while (waitpid(-1, NULL, WNOHANG) > 0)
continue;
}
static void handleRequest(int cfd)
{
char buf[BUF_SIZE];
int numread;
int size = BUF_SIZE;
int i;
printf("\n inside handling request fd : %d ", cfd);
fflush(stdout);
while (1) {
numread = read(cfd, buf, size);
if (numread > 0) {
int l = strlen(buf);
printf("Echo server numread : %d len : %d buf : %s\n", numread, l, buf);
fflush(stdout);
buf[l] = '\0';
write(cfd, buf, size);
}
}
}
int main(int argc, char *argv[])
{
int lfd, cfd;
struct sigaction sa;
sigemptyset(&sa.sa_mask);
sa.sa_handler = zombieReaper;
if (sigaction(SIGCHLD, &sa, NULL) == -1) {
printf("SIGCHILD signal");
exit(0);
}
struct sockaddr_in serv_addr, clnt_addr;
lfd = socket(AF_INET, SOCK_STREAM, 0);
if (lfd == -1) {
printf("Socket Failed");
exit(0);
}
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(atoi(argv[1]));
serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
if (bind(lfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) {
printf("bind() failed");
exit(0);
}
if (listen(lfd, MAXPENDING) < 0) {
printf("listen() failed");
exit(0);
}
socklen_t clen = sizeof(clnt_addr);
int status = 0;
for (;;) {
if (cfd = accept(lfd, (struct sockaddr *) &clnt_addr, &clen) < 0) {
printf("accept() failed");
} else {
printf("Accepted client cfd : %d\n", cfd);
switch (fork()) {
case -1:
close(cfd);
break;
case 0: // Child
close(lfd);
handleRequest(cfd);
exit(1);
default: // Parent
close(cfd);
break;
}
}
}
}
// client.c
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#define BUF_SIZE 4096
int main(int argc, char *argv[])
{
int clnt_fd;
struct sockaddr_in serv_addr;
//memset(&serv_addr, 0, sizeof(serv_addr));
char cmd[BUF_SIZE];
char buf[BUF_SIZE];
clnt_fd = socket(PF_INET, SOCK_STREAM, 0);
if (clnt_fd == -1) {
printf("socket() failed");
exit(0);
}
// prepare for connect
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(atoi(argv[2]));
serv_addr.sin_addr.s_addr = inet_addr(argv[1]);
// connect to server
if (connect(clnt_fd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) {
printf("connect() failed");
exit(0);
}
int size = BUF_SIZE;
while (1) {
printf("\n Enter a string (q to Exit) : \n ");
gets(cmd);
if (!strcmp(cmd, "q"))
break;
int n = write(clnt_fd, cmd, strlen(cmd));
n = read(clnt_fd, buf, BUF_SIZE);
printf("\n Received Results : \n %s\n", buf);
}
close(clnt_fd);
return 0;
}
【问题讨论】: