【问题标题】:Controlling prompt for command line控制命令行提示
【发布时间】:2014-04-10 12:33:11
【问题描述】:

我已经用 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 上。

我问了另一个线程 Command prompt can't accept message 有更简单的例子。

【问题讨论】:

  • 一目了然,您缺少字符串终止'\0' 处理。

标签: c loops command-line while-loop prompt


【解决方案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(stdin),并在打印提示之前尝试它,您必须添加一个标题和#ifdef 语句来处理不同的平台。

【讨论】:

    【解决方案2】:

    我在输入消息时发送了 CR+LF。

    然后我将终端仿真器的设置更改为发送 LF 或 CR。

    现在越来越好了。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-04-18
      • 1970-01-01
      • 2023-03-23
      • 2010-11-30
      • 2017-04-22
      相关资源
      最近更新 更多