I'm currently writing a very basic chatting client/server combo using the Windows console. I have successfully gotten Winsock established, and have used threads to allow for asynchronious chatting. However, this causes a problem.
When I chat with someone, there are two very strange conditions that can occur. First, if I am typing and they send, there is a condition that looks something like this:
Server: I am the server. I am typing aClient: Hiya! I'm the client!
sentince to you.
And then, if that is not met, I get this type of problem:
Client: This is me typing a sentince.
Client: Now I am going to wait at the Client: prompt to think of another one.
Client:
Server: HI!
I'm the server butting in!
What I would LIKE to do to solve both problems is to move the cursor around, and/or write the text only after it is input. The easiest way to do that would be to move text around. For example..
The client is writing a sentince when data from the server comes in. The current line the client is writing is cleared, then the server stuff is printed, and then the client's line is put below the server's stuff. Keeping the output clean.
I just have no idea how to do this. Help?
(And yes, I have tried SetConsoleCursorPosition(), but it doesn't work for what I want, at least how I used it.)
Server
Code:
// Multiple User Role-Play
// Version 0.2s
// By: Steven Merrick
#include <iostream>
#include <winsock.h>
int GetClientInput(SOCKET s);
int main()
{
int tmp;
char buffer[256];
WSADATA wsaData; // Windows Socket Data.
SOCKET sListen, sClient; // Create listening socket.
SOCKADDR_IN sInfo;
sInfo.sin_family = AF_INET; // Internet.
sInfo.sin_addr.s_addr = INADDR_ANY; // Any incoming address.
sInfo.sin_port = htons(10000); // Port 10000.
HANDLE sThread;
DWORD sTID;
tmp = WSAStartup(MAKEWORD(1,1), &wsaData); // Initialize Winsock 1.1.
if (tmp == SOCKET_ERROR)
{
std::cout << "Error in initializing Winsock: " << WSAGetLastError(); // Cout an error message.
WSACleanup(); // Shutdown Winsock
}
sListen = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); // Create an Internet Steam TCP Socket.
if (sListen == INVALID_SOCKET)
{
std::cout << "Error in creating socket: " << WSAGetLastError(); // Cout an error message.
WSACleanup(); // Shutdown Winsock
}
tmp = bind(sListen, (LPSOCKADDR)&sInfo, sizeof(struct sockaddr));
if (tmp == SOCKET_ERROR)
{
std::cout << "Error in binding socket: " << WSAGetLastError(); // Cout an error message.
WSACleanup(); // Shutdown Winsock
}
tmp = listen(sListen, 1);
if (tmp == SOCKET_ERROR)
{
std::cout << "Error in listening: " << WSAGetLastError(); // Cout an error message.
WSACleanup(); // Shutdown Winsock
}
sClient = accept(sListen, NULL, NULL);
if (sClient == SOCKET_ERROR)
{
std::cout << "Error in accepting: " << WSAGetLastError(); // Cout an error message.
WSACleanup(); // Shutdown Winsock
}
sThread = CreateThread(0, 0, (LPTHREAD_START_ROUTINE)GetClientInput, (LPVOID)sClient, 0, &sTID); // Starts thread to get input from user.
while (sClient != SOCKET_ERROR)
{
memset(buffer, NULL, sizeof(buffer)); // Clears the buffer.
recv(sClient, buffer, sizeof(buffer), 0); // Gets data.
if (buffer[0] != NULL) // If the buffer is not empty..
{
std::cout << "Client: " << buffer << "\n"; // Outputs information gotten from other client(s).
}
}
// Close sockets cleanly, shutdown Winsock.
closesocket(sClient);
closesocket(sListen);
WSACleanup();
std::cin.get();
return(0);
}
int GetClientInput(SOCKET s)
{
char buffer[256];
while (s != SOCKET_ERROR)
{
memset(buffer, 0, sizeof(buffer)); // Clears the buffer.
std::cin.getline(buffer, 256);// Gets user input.
send(s, buffer, strlen(buffer), 0); // Sends user input to other client(s).
}
return(0);
}
Client
Code:
// Multiple User Role-Play
// Version 0.2c
// By: Steven Merrick
#include <iostream>
#include <winsock.h>
int GetClientInput(SOCKET s);
int main()
{
int tmp;
char buffer[256];
WSADATA wsaData; // Windows Socket Data.
SOCKET sClient; // Create client socket.
HANDLE sThread, rThread; // Thread handle.
DWORD sTID, rTID; // Thread ID.
tmp = WSAStartup(MAKEWORD(1,1), &wsaData); // Initialize Winsock 1.1.
if (tmp == SOCKET_ERROR)
{
std::cout << "Error in initializing Winsock: " << WSAGetLastError(); // Cout an error message.
WSACleanup(); // Shutdown Winsock
}
LPHOSTENT hEntry;
hEntry = gethostbyname("lithorien.net"); // Resolves the domain 'lithorien.net'.
if (!hEntry)
{
std::cout << "Error in resolving host: " << WSAGetLastError(); // Cout an error message.
WSACleanup(); // Shutdown Winsock
}
SOCKADDR_IN sInfo;
sInfo.sin_family = AF_INET; // Internet.
sInfo.sin_addr = *((LPIN_ADDR)*hEntry->h_addr_list); // Lithorien.net, first preferred IP.
sInfo.sin_port = htons(10000); // Port 10000.
sClient = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); // Create an Internet Steam TCP Socket.
if (sClient == INVALID_SOCKET)
{
std::cout << "Error in creating socket: " << WSAGetLastError(); // Cout an error message.
WSACleanup(); // Shutdown Winsock
}
tmp = connect(sClient, (LPSOCKADDR)&sInfo, sizeof(struct sockaddr));
if (tmp == SOCKET_ERROR)
{
std::cout << "Error in initializing Winsock: " << WSAGetLastError(); // Cout an error message.
WSACleanup(); // Shutdown Winsock
}
sThread = CreateThread(0, 0, (LPTHREAD_START_ROUTINE)GetClientInput, (LPVOID)sClient, 0, &sTID); // Starts thread to get input from user.
// Gets information from the server.
while (sClient != SOCKET_ERROR)
{
memset(buffer, NULL, sizeof(buffer)); // Clears the buffer.
recv(sClient, buffer, sizeof(buffer), 0); // Gets data.
if (buffer[0] != NULL) // If the buffer is not empty..
{
std::cout << "\nServer: " << buffer << "\n"; // Outputs information gotten from other client(s).
}
}
closesocket(sClient); // Close socket cleanly.
WSACleanup(); // Shutdown Winsock
std::cin.get();
return(0);
}
int GetClientInput(SOCKET s)
{
char buffer[256];
while (s != SOCKET_ERROR)
{
memset(buffer, 0, sizeof(buffer)); // Clears the buffer.
std::cout << "Client: ";
std::cin.getline(buffer, 256); // Gets user input.
send(s, buffer, strlen(buffer), 0); // Sends user input to other client(s).
}
return(0);
}
Edit: This should probally be in the Windows Programming section. Sorry for the misplace.