在屏幕底部保持提示消息传递应用程序

时间:2015-06-07 05:58:53

标签: c network-programming command-line-interface

我正在尝试在C上开发用于网络编程实践的CLI消息传递应用程序,但我不确定如何有效地操作命令行以使其可用。目前,提示将显示“输入消息:”,但如果在用户完成输入消息之前收到消息,则可能发生以下情况: “输入一条消息:你好wClient:我正在插入你的世界”。

我想要的解决方案是在屏幕底部始终显示“输入消息”提示,其中传入和传出消息从顶部发出,就像你在基本上任何信使一样虽然我不知道如何将东西粘在终端的底部或如何以任何方式直观地影响终端。

到目前为止,这是完整的代码:

服务器

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

int main() {

  int listenfd = 0, connfd = 0;

  struct sockaddr_in serv_addr;

  char sendBuff[1025];
  char recvBuff[1025] = "test"; 

  listenfd = socket(AF_INET, SOCK_STREAM, 0);

  memset(&serv_addr, '0', sizeof(serv_addr));
  memset(sendBuff, '0', sizeof(sendBuff));

  serv_addr.sin_family = AF_INET;    
  serv_addr.sin_addr.s_addr = htonl(INADDR_ANY); 
  serv_addr.sin_port = htons(5000);    

  bind(listenfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr));

  if (listen(listenfd, 10) == -1) {
    printf("Failed to listen\n");
    return -1;
  }

  connfd = accept(listenfd, (struct sockaddr*)NULL ,NULL);

  pid_t pid = fork();
  if (pid) {
    while (strncmp(recvBuff, "exit", 4) != 0) {
      if(recv(connfd, recvBuff, sizeof(recvBuff)-1, 0) < 0)
        printf("Error: Recieve\nErrno: %d\n", errno);
      recvBuff[1024] = 0;

      printf("Client: %s", recvBuff);
    }

    wait(&pid);
    close(connfd);

  } else {
    while (strncmp(sendBuff, "exit", 4) != 0) {
      fputs("Enter a message: ", stdout);
      fgets(sendBuff, sizeof(sendBuff), stdin);

      if(send(connfd, sendBuff, sizeof(sendBuff), 0) < 0)
      printf("Error: Send\nErrno: %d\n", errno);
    }
    close(connfd);
    exit(0);
  }

  close(listenfd); 

  return 0;    

}

客户端

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

int main(void)
{
  int sockfd = 0;
  char recvBuff[1024];
  char sendBuff[1024] = "";
  struct sockaddr_in serv_addr;

  memset(recvBuff, '0' ,sizeof(recvBuff));
  if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
    printf("\n Error : Could not create socket \n");
    return 1;
  }

  serv_addr.sin_family = AF_INET;
  serv_addr.sin_port = htons(5000);
  serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1");

  if(connect(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) {
    printf("\n Error : Connect Failed \n");
    return 1;
  }

  pid_t pid = fork();
  if (pid) {
    while (strncmp(recvBuff, "exit", 4) != 0) {
      if(recv(sockfd, recvBuff, sizeof(recvBuff)-1, 0) < 0)
        printf("Error: Receive\nErrno: %d\n", errno);
      recvBuff[1024] = 0;

      printf("Server: %s", recvBuff);
    }

    wait(&pid);
    close(sockfd);

  } else {
    while (strncmp(sendBuff, "exit", 4) != 0) {
      fputs("Enter a message: ", stdout);
      fgets(sendBuff, sizeof(sendBuff), stdin);

      if(send(sockfd, sendBuff, sizeof(sendBuff), 0) < 0)
        printf("Error: Send\nErrno: %d\n", errno);
    }
    close(sockfd);
    exit(0);
  }

  return 0;
}

此外,关于编码风格或网络技术的任何附注也都很受欢迎。感谢。

2 个答案:

答案 0 :(得分:1)

我建议您使用名为Ncurses的库。它是为了创建漂亮的终端接口而不想破坏你的键盘。您将创建2个窗口,一个用于服务器聊天,另一个用于客户端聊天。

如果您不能使用外部库,最好的办法是使用转义码move the cursor。一些伪代码可能如下所示:

when server message is received
  Move cursor up one
  Write message
  Move back down

when user enters message
  print on regular line

这是一个很难处理的问题,特别是平台。所以如果可能的话,一直都是ncurses。

答案 1 :(得分:0)

有很多“逃避”的事情。用于处理终端的序列。

建议阅读:http://en.wikipedia.org/wiki/ANSI_escape_code

使用这些转义序列,程序可以保存/恢复当前光标位置。

关闭键盘回声。

当用户输入字符时。

save current cursor position
jump to next available position in user input line
echo the char
return to the prior cursor position