I'm trying to develop a CLI messaging app in C on mac for network programming practice but I'm not sure how to effectively manipulate the command line to make it usable. Currently the prompt will display "Enter a message: " but if a message comes in before the user finished typing their message something like this could happen: "Enter a message: Hello wClient: I'm interupting youorld".
The solution I'd like to have would be to have the "Enter a message" prompt always at the bottom of the screen with the incoming and outgoing messages coming down from the top as you'd have in basically any messenger, though I have no idea how to glue something to the bottom of the terminal or how to visually affect the terminal in any way.
Here's the entirety of the code so far:
Server
#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;
}
Client
#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;
}
Also any side notes about coding style or networking techniques are appreciated too. Thanks.
I'd advise you use a library called Ncurses. It was made for creating nice terminal interfaces without wanting to smash your keyboard. You would create 2 windows, one for the server chat and one for the client chat.
If you can't use external libraries, your best bet would be to use escape codes to move the cursor. Some pseudo code might look like:
This is a major pain to handle with though, and platform specific. So if possible, ncurses all the way.