-1

クライアントが接続してコマンドを待機できるサーバーTCPソケットをプログラムする方法を学んでいます...

fd = open("/tmp/myFIFO", O_RDWR);
if(fd<0){
    perror("open() error");
    exit(1);
}

do {
    while ((nbytes = read(fd, buffer, sizeof(buffer)-1)) > 0) {
        buffer[nbytes] = '\0';
        printf("%s\n", buffer);
    }
    err = recv(cFD, strbuf, sizeof(strbuf), 0);
    if (err < 0) {
        if (errno != EWOULDBLOCK) {
            perror("  recv() failed");
            state = TRUE;
        }
        break;
    }

    if (err == 0) {
        printf("  Connection closed\n");
        state = TRUE;
        break;
    }

    dSize = err;
    printf("  %d bytes received\n", dSize);
    err = send(cFD, buffer, strlen(buffer), 0);
    if (err < 0) {
        perror("  send() failed");
        state = TRUE;
        break;
    }
} while (TRUE);

問題が発生しているコードの一部を取得するだけです。私はパイプから読んでいます。私はそれを使用してクライアントにメッセージを送信しています..しかし、私の問題はrecvにあります。パイプから読み取ったデータをクライアントに送信する前に、クライアントから送信されたデータを待ちます。私がやりたいことは、データをパイプに送信するたびに、recv を待たずにクライアントに直接送信されることです。これはどのように行うことができますか?

完全なコードは次のとおりです。

#include <stdio.h>
#include <stdlib.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <netinet/in.h>
#include <errno.h>
#include <string.h>
#include <sys/select.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <pthread.h>

#define TRUE             1
#define FALSE            0

typedef struct SERVER_FD{

int sPort;
int serverFD;
int smaxFD; 
int newFD;


}sSD;

int cFD, 
    dSize, 
    err, 
    start = 1,
    state,
    DescRead,
    DCSERVER = FALSE;

struct sockaddr_in  addr, cli_addr;
unsigned long ip;
char strbuf[256];
socklen_t clilen;
fd_set fdin, fduse;

pid_t pid, sid;

int fd=-1;
int nbytes;
char buffer[256];


void process(int ServerFD, int Port, int sMax, int NewSFD);
void cleanUP(int i, int max);
void dlogs(unsigned long ip);
void daemonize();

main (int argc, char *argv[])
{
    sSD link;
    sSD *sCon;
    sCon = &link;
    sCon->sPort = 53234;

    fd = open("/tmp/myFIFO", O_RDWR);
    if(fd<0){
        perror("open() error");
        exit(1);
    }

    printf("Starting Server-G\n");

    fcntl(fd, F_SETFL,
    fcntl(fd, F_GETFL) | O_NONBLOCK);
    sCon->serverFD = socket(AF_INET, SOCK_STREAM, 0);
    if (sCon->serverFD != -1) {
        err = setsockopt(sCon->serverFD, SOL_SOCKET,  SO_REUSEADDR,(char *)&start, sizeof(start));
        if (err != -1) {
            err = ioctl(sCon->serverFD, FIONBIO, (char *)&start);
            if (err != -1){
                process(sCon->serverFD,sCon->sPort,sCon->smaxFD,sCon->newFD);
            }
            else{
                perror("ioctl() failed");
                close(sCon->serverFD);
                exit(EXIT_FAILURE);
            }
        }
        else{
            perror("setsockopt() failed");
            close(sCon->serverFD);
            exit(EXIT_FAILURE);
        }
    }
    else{
        perror("FAILED CONNECTING TO SOCKET");
        exit(EXIT_FAILURE);
   } 
}

void process(int ServerFD, int Port, int sMax, int NewSFD){
    bzero((char *) &addr, sizeof(addr));
    addr.sin_family      = AF_INET;
    addr.sin_addr.s_addr = 0;
    addr.sin_port        = htons(Port);

    err = bind(ServerFD,(struct sockaddr *)&addr, sizeof(addr));
    if (err < 0) {
        perror("bind() failed");
        close(ServerFD);
        exit(EXIT_FAILURE);
    }

    daemonize();
    err = listen(ServerFD, 32);
    if (err < 0) {
        perror("listen() failed");
        close(ServerFD);
        exit(EXIT_FAILURE);
    }
    clilen = sizeof(cli_addr);
    FD_ZERO(&fdin);
    sMax = ServerFD;
    FD_SET(ServerFD, &fdin);

    do {
        fduse = fdin;
        err = select(sMax + 1, &fduse, NULL, NULL, NULL);
        if (err < 0) {
            perror("  select() failed");
            break;
        }
        DescRead = err;
        for (cFD=0; cFD <= sMax  &&  DescRead > 0; ++cFD) {
            if (FD_ISSET(cFD, &fduse)) {
                DescRead -= 1;
                if (cFD == ServerFD) {
                    do {
                        NewSFD = accept(ServerFD,(struct sockaddr *) &cli_addr, &clilen);
                        if (NewSFD < 0) {
                            if (errno != EWOULDBLOCK) {
                                perror("  accept() failed");
                                DCSERVER = TRUE;
                            }
                            break;
                        }
                        ip = ntohl(cli_addr.sin_addr.s_addr);
                        printf("  Connection from %d.%d.%d.%d\n",
                            (int)(ip>>24)&0xff,
                            (int)(ip>>16)&0xff,
                            (int)(ip>>8)&0xff,
                            (int)(ip>>0)&0xff);
                            dlogs(ip);
                        FD_SET(NewSFD, &fdin);
                        if (NewSFD > sMax)
                            sMax = NewSFD;
                    } while (NewSFD != -1);
                }
                else {
                    state = FALSE;
                    do {
                       //PART WHERE I'm Having problems.
                        err = recv(cFD, strbuf, sizeof(strbuf), 0);
                        if (err < 0) {
                            if (errno != EWOULDBLOCK) {
                            perror("  recv() failed");
                            state = TRUE;
                            }
                            break;
                        }
                        if (err == 0) {
                            printf("  Connection closed\n");
                            state = TRUE;
                            break;
                        }
                        dSize = err;
                        printf("  %d bytes received\n", dSize);
                        while ((nbytes = read(fd, buffer, sizeof(buffer)-1)) > 0) {
                            buffer[nbytes] = '\0';
                            printf("%s\n", buffer);
                        }

                        err = send(cFD, buffer, strlen(buffer), 0);
                        if (err < 0) {
                            perror("  send() failed");
                            state = TRUE;
                            break;
                        }
                    } while (TRUE);

                    if (state) {
                        close(fd);
                        close(cFD);
                        FD_CLR(cFD, &fdin);
                        if (cFD == sMax) {
                            while (FD_ISSET(sMax, &fdin) == FALSE)
                                sMax -= 1;
                        }
                    }
                } 
            } 
        } 
    } while (DCSERVER == FALSE);
    cleanUP(cFD, sMax);
}

void cleanUP(int i, int max){
    for (i=0; i <= max; ++i) {
        if (FD_ISSET(i, &fdin))
        close(i);
    }
}

void dlogs(unsigned long ip){
    FILE* pFile = fopen("/sockF.txt", "a+");
    fprintf(pFile,"Connection from: %d.%d.%d.%d",
                    (int)(ip>>24)&0xff,
                    (int)(ip>>16)&0xff,
                    (int)(ip>>8)&0xff,
                    (int)(ip>>0)&0xff);
    fclose(pFile);
}

void daemonize(){
    pid = fork();
    if(pid<0){
        perror("fork() failed");
        exit(EXIT_FAILURE);
    }
    if(pid>0){
        exit(EXIT_SUCCESS);
    }

    umask(0);

    sid = setsid();
    if(sid<0){
        perror("setsid() failed");
        exit(EXIT_FAILURE);
    }

    if((chdir("/")) < 0){
        perror("failed changing directory");
        exit(EXIT_FAILURE);
    }
}

サンプル出力: サーバーのテストに telnet と putty を使用しています

From Telnet: IP: 192.168.5.53
Telnet 192.168.5.55 53234

./socks
Starting Server-G
Connection from: 192.168.5.53

telnetが接続されたら、パテを使用してパイプにデータを送信し、サーバーがデータを読み取るようにします。

From Putty: 
echo "TEST" > /tmp/myFIFO

ここでの問題は、パテ書き込みからパイプにデータを送信するたびに、サーバーが出力してパイプに書き込んだデータを送信する前に、telnet がデータを送信するのを待機することです。recv と read の両方を同じ tym で動作させるにはどうすればよいですか?

ありがとう

編集:パイプを読み取るためにスレッドも使用しましたが、パイプに読み取られたものをサーバーが出力する前に recv() を待機します。

4

1 に答える 1

4

selectまたはを使用pollして、両方のファイルハンドルでイベントを待機します。(を使用してpoll

#include <poll.h>

//...

struct pollfd pfds[2];
int rc;

/* Wait for input on either one of the fds */
pfds[0].fd = fd;
pfds[0].events = POLLIN;
pfds[1].fd = cFD;
pfds[1].events = POLLIN;

do {
    /* Wait forever for something to happen */
    rc = poll(&pfds, 2, -1);
    /* Error handling elided */
    if (pfds[0].revents & POLLIN)
    {
        /* Read from fd, change pfds[1].events to (POLLIN | POLLOUT) so you know when you
           can write without blocking. also clear pfds[0].events so we don't read until we
           write */
        pfds[0].events = 0;
        pfds[1].events = POLLIN | POLLOUT;
    }

    if (pfds[1].revents & POLLIN)
    {
        /* Read from socket */
    }

    if (pfds[1].revents & POLLOUT)
    {
        /* write to socket, reset events flags */
        pfds[0].events = POLLIN;
        pfds[1].events = POLLIN;
    }
} while (1)
于 2012-10-22T10:04:14.067 に答える