关于客户机/服务器echo程序的上一个问题的后续问题

关于客户机/服务器echo程序的上一个问题的后续问题,c,client-server,fork,C,Client Server,Fork,早些时候,我得到了一些很好的建议。我稍微修改了代码,当服务器在一个终端上运行,而客户端在其他窗口上运行时,代码工作正常。现在我想为这个项目做一个TUI,但我遇到了一个问题。由于服务器一直在监听客户机,因此它处于无限循环中;一旦建立了服务器,终端中就无法进行任何其他操作。我想我应该做的是使用fork(),这样服务器就可以在后台运行,让TUI自由地创建客户端。这是我迄今为止的代码(同样,我不能为客户机/服务器代码赢得太多荣誉): 服务器代码 #include <stdio.h> #inc

早些时候,我得到了一些很好的建议。我稍微修改了代码,当服务器在一个终端上运行,而客户端在其他窗口上运行时,代码工作正常。现在我想为这个项目做一个TUI,但我遇到了一个问题。由于服务器一直在监听客户机,因此它处于无限循环中;一旦建立了服务器,终端中就无法进行任何其他操作。我想我应该做的是使用fork(),这样服务器就可以在后台运行,让TUI自由地创建客户端。这是我迄今为止的代码(同样,我不能为客户机/服务器代码赢得太多荣誉):

服务器代码

#include <stdio.h>
#include <errno.h>
#include <signal.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>

struct sockaddr myname;
char buf[80];

ssize_t readLine(int sockd, char *vptr, size_t maxlen) {
ssize_t n, rc;
char c, *buffer;

buffer = vptr;

for(n = 1; n < maxlen; n++) {
    if((rc = read(sockd, &c, 1)) == 1) {
        *buffer++ = c;
        if(c== '\n')
            break;
    }
    else if(rc == 0){
        if(n == 1)
            return 0;
        else
            break;
    }
    else {
        if(errno == EINTR)
            continue;
        return -1;
    }
}
*buffer = 0;
return n;
}


ssize_t modifyBuf(int sockd, char *vptr, size_t n) {
int i, j;
char temp;

for(i = 0, j = n-1; i < j; i++, j--) {
    temp = vptr[i];
    vptr[i] = vptr[j];
    vptr[j] = temp;
}
for(i = 0; i < n; i++)
    vptr[i] = toupper(vptr[i]);

return writeLine(sockd,vptr,n);

}

ssize_t writeLine(int sockd, const void *vptr, size_t n) {
size_t nleft;
size_t nwritten;
const char *buffer;

buffer = vptr;
nleft = n;

while(nleft > 0) {
    if((nwritten = write(sockd,buffer,nleft)) <= 0){
        if(errno == EINTR)
            nwritten = 0;
        else
            return -1;
    }
    nleft -= nwritten;
    buffer += nwritten;
}
return n;
}

makeServer() {
int sock, new_sd, adrlen, cnt;

sock = socket(AF_UNIX, SOCK_STREAM, 0);
if(sock < 0) {
    printf("server socket failure %d\n", errno);
    perror("server: ");
    exit(1);
}

myname.sa_family = AF_UNIX;
strcpy(myname.sa_data, "/tmp/billb");
adrlen = strlen(myname.sa_data) + sizeof(myname.sa_family);

unlink("/tmp/billb"); /*defensive programming */
if(bind(sock, &myname, adrlen) < 0) {
    printf("server bind failure%d\n", errno);
    perror("server: ");
    exit(1);
}

if(listen(sock, 5) < 0) {
    printf("server listen failure %d\n", errno);
    perror("server: ");
    exit(1);
}

while(1) {
    if((new_sd = accept(sock, &myname, &adrlen)) < 0) {
        printf("server accept failure %d\n", errno);
        perror("server: ");
        exit(1);
    }

    printf("Socket address in server %d\n", getpid());

    if(fork() == 0) {
        close(sock);
        readLine(new_sd,buf,999);
        modifyBuf(new_sd,buf,strlen(buf));
        exit(0);
    }
    close(new_sd);
}
}
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>

char buf[80];
struct sockaddr myname;

void replyBack(FILE *fp, int sockfd) {
char sendline[1000], recvline[1000];
printf("Enter your echo: \n");
while(fgets(sendline,1000,stdin) != NULL) {
    write(sockfd,sendline,sizeof(sendline));
    if(read(sockfd,recvline,1000) == 0) {
        printf("str_cli: server terminated prematurely");
        exit(-1);
    }
    fputs(recvline, stdout);
}
}

makeClient() {
int sock, adrlen, cnt;

sock = socket(AF_UNIX, SOCK_STREAM, 0);
if(sock < 0) {
    printf("client socket failure%d\n", errno);
    printf("client: ");
    exit(1);
}

myname.sa_family = AF_UNIX;
strcpy(myname.sa_data, "/tmp/billb");
adrlen = strlen(myname.sa_data) + sizeof(myname.sa_family);

if((connect(sock, &myname, adrlen)) < 0) {
    printf("client connect failure %d\n", errno);
    perror("client: ");
    exit(1);
}

replyBack(stdin,sock);
exit(0);
}
#包括
#包括
#包括
#包括
#包括
#包括
#包括
结构sockaddr myname;
char-buf[80];
ssize_t读线(int sockd,char*vptr,size_t maxlen){
西泽屯,rc ;;
字符c,*缓冲区;
缓冲区=vptr;
对于(n=1;n0){
如果((nwrite=write(sockd、buffer、nleft))0)
showChoices();
}
TUI应该在执行时创建服务器,然后显示一个短菜单。用户可以选择创建新客户端或退出程序。如果用户创建客户端,则应提示用户向服务器发送消息;消息发送回后,应再次显示菜单。如果用户选择退出程序,则en程序将终止,插座应关闭。如果用户做出无效选择,则菜单应再次显示

现在发生的事情是服务器已经创建,我可以看到菜单,但是如果我选择创建一个新的客户端,程序就会终止,或者在我输入任何text+enter后终止(因此消息不会被发送到服务器)。正如我所说,客户端/服务器在没有TUI的情况下工作,所以我相信问题出在我使用fork()时,但我不确定还有什么其他方法可以解决这个问题


呸,太长了。谢谢您花时间!

您似乎要调用fork()两次-您肯定只想调用它一次?我认为您的代码应该是:

if(fork() == 0)
    makeServer();
else 
   showChoices();

另外,您可能需要调查wait()的用法,这将允许您等待子进程完成。

可能是同一个人提出的重复问题。这是一个后续问题,所以我不确定该放在哪里。我问的最后一个问题是关于制作客户端/服务器程序,这是关于我在TUI中遇到的问题。你是对的,我打了两次电话。我要走了阅读关于wait()的文章,这似乎是我需要的:)谢谢!
if(fork() == 0)
    makeServer();
else 
   showChoices();