first commit

This commit is contained in:
Your Name
2026-02-25 08:40:42 -06:00
commit 830c130ded
19 changed files with 677 additions and 0 deletions

13
README.md Normal file
View File

@@ -0,0 +1,13 @@
## ncursestest
A basic ncurses proof of concept test
## network more complicated
A "complicated" network system that allows for ip address and port selection but dosn't use ncurses or have threading
## network test
A better network test that doesn't allow you to use anything besides address 127.0.0.1 and port 8080 but it features properly implemented threading. The lack of ncurses prevents it from being passable as a client/server chat program because the ui gets out of sync but otherwise it actually works
## thread test
A basic example of how to use pthread
further instructions for how to use these programs are in the comments in their respective source code files

18
ncurses test/Makefile Normal file
View File

@@ -0,0 +1,18 @@
# Compiler and flags
CXX = g++
CXXFLAGS = -Wall -Wextra -O2 -std=c++17
# Linker flags
LDFLAGS = -lcurses
# Default target
all: ncursestest
# Build rule
ncursestest: ncursestest.cpp
$(CXX) $(CXXFLAGS) ncursestest.cpp -o ncursestest $(LDFLAGS)
# Clean build artifacts
clean:
rm -f ncursestest

BIN
ncurses test/ncursestest Executable file

Binary file not shown.

View File

@@ -0,0 +1,37 @@
#include <iostream>
#include <string>
#include <curses.h>
#include <unistd.h>
#include <cstring>
using namespace std;
int main()
{
initscr();//creates stdscr. important step
use_default_colors();//this apparently tells it to use default terminal colors whenever there is no color attribute applied
printw("Hello World\n");
printw("Please enter a string: ");
refresh();
char *arr = new char[1024];
getstr(arr);
printw("Wow I didn't think you'd type in THAT. You entered: ");
printw(arr);
start_color();
init_pair(1,COLOR_RED, COLOR_BLUE);
attron(COLOR_PAIR(1));
printw("\nThe quick brown fox jumps over the lazy dog\n");
attroff(COLOR_PAIR(1));
mvprintw(17, 7, "BRUUUUUUUUH");
move(12,13);
attron(A_STANDOUT | A_UNDERLINE);
mvprintw(15, 3, "");
attroff(A_STANDOUT | A_UNDERLINE);
mvaddch(4,3, '@');
refresh();
getch();
endwin();
}

View File

@@ -0,0 +1,19 @@
# Compiler and flags
CXX = g++
CXXFLAGS = -Wall -Wextra -O2 -std=c++17
# Targets
all: client server
# Client build
client: client.cpp
$(CXX) $(CXXFLAGS) client.cpp -o client
# Server build
server: server.cpp
$(CXX) $(CXXFLAGS) server.cpp -o server
# Clean build artifacts
clean:
rm -f client server

BIN
network more complicated/client Executable file

Binary file not shown.

View File

@@ -0,0 +1,86 @@
/*this network test uses more complicated network functionality but doesnt use threads or ncurses.
that means you have to wait for the other end to send a message before getting to write a new message
to run, do ./client.cpp 127.0.0.1 8080
this one has args
*/
#include <iostream>
#include <string>
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <netdb.h>
#include <sys/uio.h>
#include <sys/time.h>
#include <sys/wait.h>
#include <fcntl.h>
#include <fstream>
using namespace std;
//Client side
int main(int argc, char *argv[])
{
//we need 2 things: ip address and port number, in that order
if(argc != 3)
{
cerr << "Usage: ip_address port" << endl; exit(0);
} //grab the IP address and port number
char *serverIp = argv[1]; int port = atoi(argv[2]);
//create a message buffer
char msg[1500];
//setup a socket and connection tools
struct hostent* host = gethostbyname(serverIp);
sockaddr_in sendSockAddr;
bzero((char*)&sendSockAddr, sizeof(sendSockAddr));
sendSockAddr.sin_family = AF_INET;
sendSockAddr.sin_addr.s_addr =
inet_addr(inet_ntoa(*(struct in_addr*)*host->h_addr_list));
sendSockAddr.sin_port = htons(port);
int clientSd = socket(AF_INET, SOCK_STREAM, 0);
//try to connect...
int status = connect(clientSd,
(sockaddr*) &sendSockAddr, sizeof(sendSockAddr));
if(status < 0)
{
cout<<"Error connecting to socket!"<<endl;// break;
}
cout << "Connected to the server!" << endl;
int bytesRead, bytesWritten = 0;
struct timeval start1, end1;
gettimeofday(&start1, NULL);
while(1)
{
cout << ">";
string data;
getline(cin, data);
memset(&msg, 0, sizeof(msg));//clear the buffer
strcpy(msg, data.c_str());
if(data == "exit")
{
send(clientSd, (char*)&msg, strlen(msg), 0);
break;
}
bytesWritten += send(clientSd, (char*)&msg, strlen(msg), 0);
cout << "Awaiting server response..." << endl;
memset(&msg, 0, sizeof(msg));//clear the buffer
bytesRead += recv(clientSd, (char*)&msg, sizeof(msg), 0);
if(!strcmp(msg, "exit"))
{
cout << "Server has quit the session" << endl;
break;
}
cout << "Server: " << msg << endl;
}
gettimeofday(&end1, NULL);
close(clientSd);
cout << "********Session********" << endl;
cout << "Bytes written: " << bytesWritten <<
" Bytes read: " << bytesRead << endl;
cout << "Elapsed time: " << (end1.tv_sec- start1.tv_sec)
<< " secs" << endl;
cout << "Connection closed" << endl;
return 0;
}

BIN
network more complicated/server Executable file

Binary file not shown.

View File

@@ -0,0 +1,117 @@
/*this network test uses more complicated network functionality but doesnt use threads or ncurses.
that means you have to wait for the other end to send a message before getting to write a new message
to run, do ./server.cpp 8080
this one has args
*/
#include <iostream>
#include <string>
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <netdb.h>
#include <sys/uio.h>
#include <sys/time.h>
#include <sys/wait.h>
#include <fcntl.h>
#include <fstream>
using namespace std;
//Server side
int main(int argc, char *argv[])
{
//for the server, we only need to specify a port number
if(argc != 2)
{
cerr << "Usage: port" << endl;
exit(0);
}
//grab the port number
int port = atoi(argv[1]);
//buffer to send and receive messages with
char msg[1500];
//setup a socket and connection tools
sockaddr_in servAddr;
bzero((char*)&servAddr, sizeof(servAddr));
servAddr.sin_family = AF_INET;
servAddr.sin_addr.s_addr = htonl(INADDR_ANY);
servAddr.sin_port = htons(port);
//open stream oriented socket with internet address
//also keep track of the socket descriptor
int serverSd = socket(AF_INET, SOCK_STREAM, 0);
if(serverSd < 0)
{
cerr << "Error establishing the server socket" << endl;
exit(0);
}
//bind the socket to its local address
int bindStatus = bind(serverSd, (struct sockaddr*) &servAddr,
sizeof(servAddr));
if(bindStatus < 0)
{
cerr << "Error binding socket to local address" << endl;
exit(0);
}
cout << "Waiting for a client to connect..." << endl;
//listen for up to 5 requests at a time
listen(serverSd, 5);
//receive a request from client using accept
//we need a new address to connect with the client
sockaddr_in newSockAddr;
socklen_t newSockAddrSize = sizeof(newSockAddr);
//accept, create a new socket descriptor to
//handle the new connection with client
int newSd = accept(serverSd, (sockaddr *)&newSockAddr, &newSockAddrSize);
if(newSd < 0)
{
cerr << "Error accepting request from client!" << endl;
exit(1);
}
cout << "Connected with client!" << endl;
//lets keep track of the session time
struct timeval start1, end1;
gettimeofday(&start1, NULL);
//also keep track of the amount of data sent as well
int bytesRead, bytesWritten = 0;
while(1)
{
//receive a message from the client (listen)
cout << "Awaiting client response..." << endl;
memset(&msg, 0, sizeof(msg));//clear the buffer
bytesRead += recv(newSd, (char*)&msg, sizeof(msg), 0);
if(!strcmp(msg, "exit"))
{
cout << "Client has quit the session" << endl;
break;
}
cout << "Client: " << msg << endl;
cout << ">";
string data;
getline(cin, data);
memset(&msg, 0, sizeof(msg)); //clear the buffer
strcpy(msg, data.c_str());
if(data == "exit")
{
//send to the client that server has closed the connection
send(newSd, (char*)&msg, strlen(msg), 0);
break;
}
//send the message to client
bytesWritten += send(newSd, (char*)&msg, strlen(msg), 0);
}
//we need to close the socket descriptors after we're all done
gettimeofday(&end1, NULL);
close(newSd);
close(serverSd);
cout << "********Session********" << endl;
cout << "Bytes written: " << bytesWritten << " Bytes read: " << bytesRead << endl;
cout << "Elapsed time: " << (end1.tv_sec - start1.tv_sec)
<< " secs" << endl;
cout << "Connection closed..." << endl;
return 0;
}

19
network test/Makefile Normal file
View File

@@ -0,0 +1,19 @@
# Compiler and flags
CXX = g++
CXXFLAGS = -Wall -Wextra -O2 -std=c++17
# Targets
all: client server
# Client build
client: client.cpp
$(CXX) $(CXXFLAGS) client.cpp -o client
# Server build
server: server.cpp
$(CXX) $(CXXFLAGS) server.cpp -o server
# Clean build artifacts
clean:
rm -f client server

BIN
network test/client Executable file

Binary file not shown.

94
network test/client.cpp Normal file
View File

@@ -0,0 +1,94 @@
// Client side C/C++ program to demonstrate Socket programming
//this uses threads to allow a server and a client to do network chat stuff over 127.0.0.1:8080. the ui is out of sync because it doesn't use ncurses but the message sending and printing part still works
#include <stdio.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <string.h>
#include <string>
#include <iostream>
#include <thread>
#define PORT 8080
using namespace std;
#ifdef _WIN32
/#include <windows.h>;
void fnsleep(unsigned milliseconds)
{
Sleep(milliseconds);
}
#else
#include <unistd.h>
void fnsleep(unsigned milliseconds)
{
usleep(milliseconds * 1000);
}
#endif
void checkForNewMsgs(int socket, int valreaded, int otherNum);
void checkForNewMsgs(int socket, int valreaded, int otherNum)
{
int valreadOne;
char newBuffer[1024] = {0};
while (3 == 3 && newBuffer != "exit")
{
for(int i = 0; i < 1024; i++)
{
newBuffer[i] = char(0);
}
valreadOne = read( socket , newBuffer, 1024);
if (newBuffer != "")
{
cout << "Server: ";
printf("%s\n",newBuffer );
}
}
fnsleep(1000);
}
int main(int argc, char const *argv[])
{
int sock = 0, valread;
struct sockaddr_in serv_addr;
char *hello = "Hello from client";
char buffer[1024] = {0};
if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0)
{
printf("\n Socket creation error \n");
return -1;
}
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(PORT);
// Convert IPv4 and IPv6 addresses from text to binary form
if(inet_pton(AF_INET, "127.0.0.1", &serv_addr.sin_addr)<=0)
{
printf("\nInvalid address/ Address not supported \n");
return -1;
}
if (connect(sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0)
{
printf("\nConnection Failed \n");
return -1;
}
string message;
thread t(checkForNewMsgs, sock, valread, 1024);
t.detach();
while (message != "exit")
{
cout << "> ";
getline(cin, message);
send(sock , message.c_str() , strlen(message.c_str()) , 0 );
//printf("Hello message sent\n");
//valread = read( sock , buffer, 1024);
//printf("%s\n",buffer );
}
return 0;
}

BIN
network test/server Executable file

Binary file not shown.

114
network test/server.cpp Normal file
View File

@@ -0,0 +1,114 @@
// Server side C/C++ program to demonstrate Socket programming
//this uses threads to allow a server and a client to do network chat stuff over 127.0.0.1:8080. the ui is out of sync because it doesn't use ncurses but the message sending and printing part still works
#include <unistd.h>
#include <stdio.h>
#include <sys/socket.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <string.h>
#include <thread>
#include <iostream>
using namespace std;
#define PORT 8080
#ifdef _WIN32
/#include <windows.h>;
void fnsleep(unsigned milliseconds)
{
Sleep(milliseconds);
}
#else
#include <unistd.h>
void fnsleep(unsigned milliseconds)
{
usleep(milliseconds * 1000);
}
#endif
void checkForNewMsgs(int socket, int valreaded, int otherNum);
void checkForNewMsgs(int socket, int valreaded, int otherNum)
{
int valreadOne;
char newBuffer[1024] = {0};
while (3 == 3 && newBuffer != "exit")
{
//printf("Client: ");
for(int i = 0; i < 1024; i++)
{
newBuffer[i] = char(0);
}
valreadOne = read( socket , newBuffer, 1024);
if (newBuffer != "")
{
printf("Client: ");
printf("%s\n",newBuffer );
}
}
fnsleep(1000);
}
int main(int argc, char const *argv[])
{
int server_fd, new_socket, valread;
struct sockaddr_in address;
int opt = 1;
int addrlen = sizeof(address);
char buffer[1024] = {0};
char *hello = "Hello from server";
// Creating socket file descriptor
if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0)
{
perror("socket failed");
exit(EXIT_FAILURE);
}
// Forcefully attaching socket to the port 8080
if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT,
&opt, sizeof(opt)))
{
perror("setsockopt");
exit(EXIT_FAILURE);
}
address.sin_family = AF_INET;
address.sin_addr.s_addr = INADDR_ANY;
address.sin_port = htons( PORT );
// Forcefully attaching socket to the port 8080
if (bind(server_fd, (struct sockaddr *)&address,
sizeof(address))<0)
{
perror("bind failed");
exit(EXIT_FAILURE);
}
if (listen(server_fd, 3) < 0)
{
perror("listen");
exit(EXIT_FAILURE);
}
if ((new_socket = accept(server_fd, (struct sockaddr *)&address,
(socklen_t*)&addrlen))<0)
{
perror("accept");
exit(EXIT_FAILURE);
}
string message;
thread t(checkForNewMsgs, new_socket, valread, 1024);
t.detach();
while (message != "exit")
{
//string message;
cout << "> ";
getline(cin, message);
//valread = read( new_socket , buffer, 1024);
//printf("%s\n",buffer );
send(new_socket , message.c_str() , strlen(message.c_str()) , 0 );
//cout << "Hello message sent" << endl;
}
return 0;
}

21
thread test/Makefile Normal file
View File

@@ -0,0 +1,21 @@
# Compiler and flags
CXX = g++
CXXFLAGS = -pthread -Wall -Wextra -O2 -std=c++17
# Linker flags
LDFLAGS = -lcurses
# Default target
all: thread threadncurses
# Build rule
thread: thread.cpp
$(CXX) $(CXXFLAGS) thread.cpp -o thread $(LDFLAGS)
threadncurses: threadncurses.cpp
$(CXX) $(CXXFLAGS) threadncurses.cpp -o threadncurses $(LDFLAGS)
# Clean build artifacts
clean:
rm -f thread threadncurses

BIN
thread test/thread Executable file

Binary file not shown.

49
thread test/thread.cpp Normal file
View File

@@ -0,0 +1,49 @@
//compile with "g++ -pthread thread.cpp -o main"
//note to self: try to use ncurses in the next one
#include <iostream>
#include <thread>
#include <stdlib.h>
#include <stdio.h>
using namespace std;
#ifdef _WIN32
//this part has never been tested and is unlikely to work
#include <windows.h>;
void fnsleep(unsigned milliseconds)
{
Sleep(milliseconds);
}
#else
#include <unistd.h>
void fnsleep(unsigned milliseconds)
{
usleep(milliseconds * 1000);
}
#endif
void helloWorld(int y)
{
for (int i = 0; i < 10; i++)
{
//a terrible, awful way of getting linux terminal text colors without ncurses.
cout << "\033[1;31mbold red text\033[0m\n";
cout << "\x1B[32mAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\x1B[0m\n";
cout << "Hello world #" << i + 1 << endl;
fnsleep(1000);
}
}
int main()
{
thread thread_object(helloWorld, 1);
cout << "This string gets printed after running the hello world function but prints BEFORE helloworld prints. That means this program uses threads" << endl;
//use detach to make the thread run asychronoussly. use join to WAIT HERE until its finished. Try it out! (i tested both cases and it works on my machine)
//thread_object.detach();
thread_object.join();
cout << "Please enter your name: " << endl;
string name;
cin >> name;
cout << name << " is a [redacted for academic purposes]" << endl;
return 0;
}

BIN
thread test/threadncurses Executable file

Binary file not shown.

View File

@@ -0,0 +1,90 @@
//compile with "g++ -pthread threadncurses.cpp -o main -lncurses"
//the same as thread.cpp but it uses ncurses instead. This proves that ncurses can work even if its in a seperate thread
//this is a very functional example of ncurses and asynchronous threading working in the same program
#include <iostream>
#include <thread>
#include <stdlib.h>
#include <stdio.h>
#include <ncurses.h>
using namespace std;
#ifdef _WIN32
//this part has never been tested and is unlikely to work
#include <windows.h>;
void fnsleep(unsigned milliseconds)
{
Sleep(milliseconds);
}
#else
#include <unistd.h>
void fnsleep(unsigned milliseconds)
{
usleep(milliseconds * 1000);
}
#endif
void helloWorld(int y)
{
for (int i = 0; i < 10; i++)
{
//store the cursor positions here
int y, x;
int yy, xx;
int xBefore;
int yBefore;
start_color();
init_pair(1, COLOR_RED, COLOR_BLUE);
if (i != 0)
{
//print the hello world lines
getyx(stdscr, yBefore, xBefore);
move(2, 0);
clrtoeol();
mvprintw(2, 0, "Hello world #");
int icantthinkofanameforthis = i + 1;
printw(to_string(icantthinkofanameforthis).c_str());//an annoying but reliable way to get this to work
printw("\n");
move(yBefore, xBefore); //move the cursor back to where is was before to allow for a fluid typing experience (i.e. its possible to mess this part up if you do it wrong)
}
else
{
attron(COLOR_PAIR(1));
attron(A_BOLD);
getyx(stdscr, yy, xx);
printw("bold red text\n");
attroff(COLOR_PAIR(1));
printw("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n");
attroff(A_BOLD);
printw("Hello world #");
int icantthinkofanameforthis = i + 1;
printw(to_string(icantthinkofanameforthis).c_str());//an annoying but reliable way to get this to work
printw("\n");
move(3, 25); //the default text-entry position
}
refresh();
fnsleep(1000);
}
}
int main()
{
initscr();
use_default_colors();
move(3, 0);
printw("Please enter your name: \n");
move(0, 0);
thread thread_object(helloWorld, 1);
thread_object.detach();
char *name = new char[99];
getstr(name);
printw(name);
printw(" is a [redacted for academic purposes]\n");
printw("Press any key to continue");
getch();
endwin();
return 0;
}