Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/67.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/linux/24.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/vim/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
TCP并发回显服务器无法从第一个客户端读取字符串_C_Linux_Sockets_Tcp - Fatal编程技术网

TCP并发回显服务器无法从第一个客户端读取字符串

TCP并发回显服务器无法从第一个客户端读取字符串,c,linux,sockets,tcp,C,Linux,Sockets,Tcp,我正在为每个客户端并发echo服务器实现一个简单的TCP进程。服务器无法从第一个客户端读取字符串。但是,对于其他客户端,服务器会正确地回显字符串。我觉得读字符串可能有问题;服务器端无法检测到EOF。我尝试使用send()/recv()而不是read()/write(),但没有成功。我还尝试了从stdin读取字符串的其他函数,即fgets()、scanf()等 这个问题的可能原因是什么;i、 e.服务器无法仅从第一个客户端读取 服务器和客户端的代码如下- // server.c #include

我正在为每个客户端并发echo服务器实现一个简单的TCP进程。服务器无法从第一个客户端读取字符串。但是,对于其他客户端,服务器会正确地回显字符串。我觉得读字符串可能有问题;服务器端无法检测到EOF。我尝试使用send()/recv()而不是read()/write(),但没有成功。我还尝试了从stdin读取字符串的其他函数,即fgets()、scanf()等

这个问题的可能原因是什么;i、 e.服务器无法仅从第一个客户端读取

服务器和客户端的代码如下-

// 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;
}
//server.c
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#定义BUF_尺寸4096
#定义MAXPENDING 256
静态无效僵尸收割器(int sig)
{
while(waitpid(-1,NULL,WNOHANG)>0)
继续;
}
静态孔隙HandlerRequest(内部cfd)
{
字符大小[buf_SIZE];
国际货币联盟;
int size=BUF_size;
int i;
printf(“\n内部处理请求fd:%d”,cfd);
fflush(stdout);
而(1){
numread=读取(cfd、buf、尺寸);
如果(numread>0){
int l=strlen(buf);
printf(“Echo服务器numread:%d len:%d buf:%s\n”,numread,l,buf);
fflush(stdout);
buf[l]='\0';
写入(cfd、buf、尺寸);
}
}
}
int main(int argc,char*argv[])
{
国际lfd,cfd;
struct-sigaction-sa;
sigemptyset(和sa.sa_面具);
sa.sa_handler=僵尸收割者;
if(sigaction(SIGCHLD,&sa,NULL)=-1){
printf(“SIGCHILD信号”);
出口(0);
}
服务地址中的结构sockaddr\u,clnt\u addr;
lfd=套接字(AF_INET,SOCK_STREAM,0);
如果(lfd==-1){
printf(“套接字失败”);
出口(0);
}
serv_addr.sin_family=AF_INET;
serv_addr.sinu 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(“绑定()失败”);
出口(0);
}
if(侦听(lfd,MAXPENDING)<0){
printf(“listen()失败”);
出口(0);
}
socklen\u t clen=sizeof(clnt\u addr);
int status=0;
对于(;;){
如果(cfd=接受(lfd,(结构sockaddr*)和clnt_addr,&clen)<0){
printf(“接受()失败”);
}否则{
printf(“接受的客户差价合约:%d\n”,差价合约);
开关(fork()){
案例1:
关闭(cfd);
打破
案例0://儿童
关闭(lfd);
HandlerRequest(cfd);
出口(1);
默认值://Parent
关闭(cfd);
打破
}
}
}
}
//客户c
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#定义BUF_尺寸4096
int main(int argc,char*argv[])
{
国际clnt\U fd;
服务地址中的结构sockaddr\u;
//memset(&serv_addr,0,sizeof(serv_addr));
char cmd[BUF_SIZE];
字符大小[buf_SIZE];
clnt_fd=套接字(PF_INET,SOCK_STREAM,0);
如果(clnt_fd==-1){
printf(“套接字()失败”);
出口(0);
}
//准备连接
serv_addr.sin_family=AF_INET;
serv_addr.sinu port=htons(atoi(argv[2]);
serv_addr.sin_addr.s_addr=inet_addr(argv[1]);
//连接到服务器
if(connect(clnt_fd,(struct sockaddr*)&serv_addr,sizeof(serv_addr))<0){
printf(“connect()失败”);
出口(0);
}
int size=BUF_size;
而(1){
printf(“\n输入字符串(q以退出):\n”);
获取(cmd);
如果(!strcmp(cmd,“q”))
打破
int n=写入(clnt_fd,cmd,strlen(cmd));
n=读取(clnt\u fd、buf、buf\u大小);
printf(“\n收到的结果:\n%s\n”,buf);
}
关闭(clnt\U fd);
返回0;
}
这里假设缓冲区中存在空值。相反,您应该只使用下面的
numread

        printf("Echo server numread : %d len : %d buf : %s\n", numread, l, buf);
这里再次假设缓冲区中存在空值。应该是

        printf("Echo server numread : %d buf : %.*s\n", numread, numread, buf);
现在: buf[l]='\0'

在这里,如果您找到了空值,您将在您已经找到它的位置放置空值。移除

        write(cfd, buf, size);
在这里,您将错误数量的数据写回发件人。它应该是
write(cfd、buf、numread)。
}


如果
numread代码中的问题是

if (cfd = accept(lfd, (struct sockaddr *) &clnt_addr, &clen) < 0)
if(cfd=accept(lfd,(struct sockaddr*)和clnt\u addr,&clen)<0)
在这里,当您接受时,您正在使用关系运算符<0测试accept的返回值

验证后,返回值0存储在cfd中

假设原始接受套接字id为4,但返回值为0

根据返回值,您正在程序中执行某些操作

尝试对以下条件使用优先级:

if ((cfd = accept(lfd, (struct sockaddr *) &clnt_addr, &clen)) < 0)
if((cfd=accept(lfd,(struct sockaddr*)和clnt_addr,&clen))<0)

现在,它将打印准确的已接受套接字id。

感谢以上建议。我在代码中实现了它们。但早期的问题仍然存在。服务器正确地回显除第一个客户端之外的所有客户端的字符串。这个问题的原因是什么?哦,网络代码中误用了strlen()。这是新的:(从这个bug的存在可以看出OP没有向我们展示“真实”的代码,因为这个bug没有客户会得到答案。我不明白,你在问什么?我什么都没问。我只是注意到,你所指的bug(显然在显示的代码中存在)实际上不允许任何客户端接收任何数据。
if (cfd = accept(lfd, (struct sockaddr *) &clnt_addr, &clen) < 0)
if ((cfd = accept(lfd, (struct sockaddr *) &clnt_addr, &clen)) < 0)