控制装置,用于命令行提示(Controlling prompt for command line)

2019-10-19 12:41发布

我已经做C.基于UDP的客户端和服务器示例程序

我的代码如下

[服务器]

    #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;

[客户]

#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;

在客户端显示的提示,使操作者键入一些信息到服务器。

服务器相呼应的消息到什么最初客户端发送的客户端。

但是,客户端发送消息3次没有在像波纹管提示和操作员的行动等。

[客户]

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)>>>

另外,服务器接收3条消息既包括ping我打,我没想到。

[服务器]

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

现在,我要问你,我怎么可以把它等待每一个提示?

此外,这不会发生在Windows上,只发生在CentOS。

我问另一个线程命令提示符无法接受的消息更简单的例子。

Answer 1:

你从终端获取杂散换行。 不知道是什么原因造成的。 如果一个空行是无效的输入,则只需忽略以“\ n”开头的行解决这个问题 - 即:

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

否则,你就必须有一些特定于平台的代码来处理清除任何缓冲输入,在Linux上我想看看fpurge(标准输入),并打印提示之前尝试它,你就必须添加页眉和#ifdef语句虽然以应对不同的平台。



Answer 2:

我发送CR + LF当我输入消息。

然后,我改变终端emulater的设定发送LF或CR。

现在越来越好。



文章来源: Controlling prompt for command line