开发者

C Socket Send() doesn't send until program terminates

This is my first question, so your grace would be appreciated. I'm trying to learn C Sockets for Unix. As part of my learning, I tried to code a simple telnet-like client that connects to a host on a specified port, prints any characters received from the server, and sends anything the user writes to the console. It receives fine, but when I try to send a string, nothing happens. Then, when I interrupt the program, all the strings I tried to send get sent. Thanks in advanced. I'm probably just being stupid.

#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netdb.h>
#include <netinet/in.h>
#include <errno.h>
#include <stdlib.h>
#include <signal.h>
#include <fcntl.h>

int SetupSock(char *host, char *port) {
    int s, status;  
    struct addrinfo hints, *res;
    memset(&hints, 0, sizeof hints);
    hints.ai_family = AF_UNSPEC;
    hints.ai_socktype = SOCK_STREAM;
    getaddrinfo(host, port, &hints, &res);  
    if((s = socket(res->ai_family, res->ai_socktype, res->ai_protocol)) == -1) {
        printf("Could not create sock...root?\n");
        exit(1);
    }
    if((status = connect(s, res->ai_addr, res->ai_addrlen)) == -1) {
        printf("Connect Failed: %s\n", strerror(errno));
        printf("%s", strerror( errno ));
        printf("\n");       
        exit(1);
    }
    return s;
}

int main (void) {
    char *host = malloc(100), *port = malloc(20), buf[2], *msg = malloc(1000);
    struct timeval waitid;
    fd_set read_flags, write_flags;
    signal(SIGPIPE, SIG_IGN);
    int sock, flags;
    //Input Host and Port
    printf("Host: ");
    gets(host);
    printf("Port: ");
    gets(port);
    sock = SetupSock(host, port);
    flags = fcntl(sock, F_GETFL, 0);
    fcntl(sock, F_SETFL, flags | O_NONBLOCK);
    FD_ZERO(&read_flags);
    FD_ZERO(&write_flags);
    FD_SET(sock, &read_flags);
    FD_SET(fileno(stdin), &read_flags);
    fflush(0);
    int pid = fork();
    if (pid == 0) {
        int status;
        close(stdout);
        while(1) {
        select(sock + 1, &read_flags, &write_flags, (fd_set*) 0, &waitid);
        if (FD_ISSET(fileno(stdin), &read_flags)) {
            gets(msg);
            if((status = send(sock, msg, strlen(msg), MSG_NOSIGNAL)) == -1) {
                printf("Send Failed: %s\n", strerror(errno));
            }
        }
        }
    }
    else {
        close(stdin);
        while(1) {
            select(sock + 1, &read_flags, &wri开发者_Go百科te_flags, (fd_set*) 0, &waitid);
            if (FD_ISSET(sock, &read_flags)) {
                if(recv(sock, &buf, 1, 0) > 0){     
                    printf("%s", buf);
                }
            }
        }
    }
    close(sock);
    return 0;
}


Your select is performed only once here. It should be inside a loop. select just waits for an event to occur on the provided set of file descriptors. It should be called again after each event has been processed.


To cover an area the other answer missed: select and stdio do not mix. You cannot get an accurate result for whether stdin is readable by whether fileno(stdin) is readable due to buffering.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜