Controlling prompt for command line

若如初见. 提交于 2019-12-24 09:43:58

问题


I've made udp based client and server sample programs with C.

My codes are followings

[Server]

    #include <stdio.h>
    #include <string.h>
    #include <errno.h>
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <netdb.h>
    #include <arpa/inet.h>


    int printerror2(char func[], int errnum)
    {
        printf("%s error = %d:%s\n", func, errnum, strerror(errnum));
        perror(func);
        return errnum;
    }

    int printerror(char func[])
    {
        return printerror2(func, errno);
    }

    int main(int argc, char *argv[])
    {
        int ret;
    /*
        WSADATA wsaData;
        ret = WSAStartup(MAKEWORD(2,2), &wsaData);
        if (ret != 0)
            return printerror2("WSAStartup()", ret);
    */
        int sock;
        int port;
        struct sockaddr_in addr;
        struct sockaddr_in from;
        int from_size;

        char buf[2048];

        port = atoi(argv[1]);
        printf("############# udpServer port number is %hu\n", port);

        sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
        if (sock == -1)
            return printerror("socket()");

        memset(&addr, 0, sizeof(addr));
        addr.sin_family = AF_INET;
        addr.sin_port = htons(port);
        addr.sin_addr.s_addr = INADDR_ANY;

        ret = bind(sock, (struct sockaddr *)&addr, sizeof(addr));
        if (ret == -1)
            return printerror("bind()");

        do
        {
            from_size = sizeof(from);

            ret = recvfrom(sock, buf, sizeof(buf), 0, (struct sockaddr *)&from, &from_size);
            if (ret == -1)
                return printerror("recvfrom()");

            printf("received '%*s'(%d) from %s:%d\n",
                ret, buf, ret, inet_ntoa(from.sin_addr), ntohs(from.sin_port));

            ret = sendto(sock, buf, ret, 0, (struct sockaddr *)&from, from_size);
            if (ret == -1)
                return printerror("sendto()");

            printf("sent back '%*s'(%d) to %s:%d\n",
                ret, buf, ret, inet_ntoa(from.sin_addr), ntohs(from.sin_port));
            printf("\n");
        } 
        while  (strncmp(buf, "bye", 3) != 0);

        printf("bye now");

        close(sock);
        return 0;

[Client]

#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <arpa/inet.h>

int printerror2(char func[], int errnum)
{
    printf("%s error = %d:%s\n", func, errnum, strerror(errnum));
    perror(func);
    return errnum;
}

int printerror(char func[])
{
    return printerror2(func, errno);
}

int getMyPortNum(int sock, int *port)
{
    struct sockaddr_in s;
    socklen_t sz = sizeof(s);
    int ret = getsockname(sock, (struct sockaddr *)&s, &sz);
    if (ret == 0)
       *port = s.sin_port;
    printf("getsockname() error ret = %d:%s\n",ret,strerror(errno));
    printf("Client port(getsockname) is %d\n", ntohs(*port));
    return ret;
}

int main(int agrc, char *argv[])
{
    int ret;
/*
    WSADATA wsaData;
    ret = WSAStartup(MAKEWORD(2,2), &wsaData);
    if (ret != 0)
        return printerror2("WSAStartup", ret);
*/
    char *host;
    int port;
    int sock;
    struct sockaddr_in dst_addr;
    struct sockaddr_in src_addr;
    struct sockaddr_in from_addr;
    int from_size;

    char message[2048];
    char comnd[2048];
    char buf[2048];

    host = argv[1];
    port = atoi(argv[2]);

    printf("host = %s\n", host);
    printf("port = %d\n", port);

    sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
    if (sock == -1)
        return printerror("socket()");

    memset(&src_addr, 0, sizeof(src_addr));
    src_addr.sin_family = AF_INET;
    src_addr.sin_addr.s_addr = INADDR_ANY;
    src_addr.sin_port = 0;

    ret = bind(sock, (struct sockaddr *)&src_addr, sizeof(src_addr));
        printf("bind() error ret = %d:%s\n",ret,strerror(errno));
   if (ret == -1)
        return printerror("bind()");

    ret = getMyPortNum(sock, &(src_addr.sin_port));
    printf("Client port(getsockname) is %d\n", ntohs(src_addr.sin_port));
    if (ret == -1)
        return printerror("getsockname()");

    printf("Client port is %d\n", ntohs(src_addr.sin_port));

    memset(&dst_addr, 0, sizeof(dst_addr));
    dst_addr.sin_family = AF_INET;
    dst_addr.sin_addr.s_addr = inet_addr(host);
    dst_addr.sin_port = htons(port);

    do
    {
        printf("type your message (exit: stop Client, bye: stop server)>>>\t"); 
        fgets(buf, sizeof(buf), stdin);

        if (strcmp(buf, "exit") == 0)
            break;

        ret = sendto(sock, buf, strlen(buf), 0, (struct sockaddr *)&dst_addr, sizeof(dst_addr));
        if (ret == -1)
            return printerror("sendto()");

        printf("Waiting for send back !!!\n");

        from_size = sizeof(from_addr);

        ret = recvfrom(sock, buf, sizeof(buf), 0, (struct sockaddr *)&from_size, &from_size); 
        if (ret == -1)
            return printerror("recvfrom()");

        printf("Received '%*s' from %s:%d\n",
            ret, buf, inet_ntoa(from_addr.sin_addr), ntohs(from_addr.sin_port));
    }
    while ((strncmp(buf, "bye", 3) != 0)&&(strncmp(buf, "exit", 4) != 0));

    close(sock);
    return 0;

The client shows prompt to make operator type some message to the server.

The server echoes message to the client what the originally the client was sent.

But the client send message 3 times without waiting at prompt and operators action like bellow.

[Client]

type your message (exit: stop Client, bye: stop server)>>>      ping

Waiting for send back !!!
Received '
' from 0.0.0.0:1
type your message (exit: stop Client, bye: stop server)>>>      Waiting for send back !!!
Received 'ping
' from 0.0.0.0:1
type your message (exit: stop Client, bye: stop server)>>>      Waiting for send back !!!
Received '
' from 0.0.0.0:1
type your message (exit: stop Client, bye: stop server)>>>

Also the server receives 3 messages including both ping I typed and I didn’t expect to.

[Server]

received '
'(1) from 127.0.0.1:52804
sent back '
'(1) to 127.0.0.1:52804

received 'ping
'(5) from 127.0.0.1:52804
sent back 'ping
'(5) to 127.0.0.1:52804

received '
ing
'(1) from 127.0.0.1:52804
sent back '
ing
'(1) to 127.0.0.1:52804

Now,I want to ask you how can I make it wait each prompt?

In addition this doesn't happen on windows ,only happens on CentOS.

I asked it another thread Command prompt can't accept message with more simple example.


回答1:


You're getting stray newlines from the terminal. Not sure what is causing it. If a blank line is not valid input, you can solve this by just ignoring lines that start with '\n' -- i.e.:

printf("type your message (exit: stop Client, bye: stop server)>>>\t"); 
do {
    fgets(buf, sizeof(buf), stdin);
} while (buf[0] == '\n');

Otherwise, you will have to have some platform specific code to deal with clearing any buffered input, on linux I would look at fpurge(stdin), and try it before printing the prompt, you'll have to add a header and #ifdef statements to deal with different platforms though.




回答2:


I sent CR+LF when I typed message.

Then I changed setting of terminal emulater to send LF or CR.

Now getting better.



来源:https://stackoverflow.com/questions/22248781/controlling-prompt-for-command-line

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!