Chat server volder en del problemer.
Hejsa igen igen eksperter, jeg har arbejdet med en chat i en del uger nu, og er desværre stødt ind i nogle problemer jeg absolut ikke kan løse, har stort set forsøgt alt og kigget alle steder. Chatten er et server program som enhver kan logge på via telnet, og skrive løs ud fra det nick de har valgt, men jeg har følgende problemstillinger.Problemstillinger:
- Min chat crasher hvis MAXCLI bliver højere end 0, og den fungere faktisk fint selvom MAXCLI er = 0, men det udgøre bare at der kun kan være omkring 100 clienter online på samme tid.
- /tell funktionen virker ikke optimalt, den virker egentlig udmærket, men hvis personen logger ud, og man skriver til personen siger den "Personen er ikke online", men hvis så personen logger ind igen og vil skrive til personen, siger den stadig "Personen er ikke online".
- Folk er begyndt at bruge piletasterne hvilket gør at markøren flytter sig i telnet, det får chatten til at se totalt åndssvag ud når folk skriver oven i hinanden osv. Har forsøgt at skrive:
else if(strstr(input,"0xFF4B[A")=='\0')
og:
else if(strstr(input,"[A")=='\0')
Men så sletter den stort set alle taster.. Tasterne som jeg vil undgå er: ←[A og ←[B og ←[C og ←[D
Og sourcekode:
#include <iostream>
#include <windows.h>
#include <string>
#include <map>
using namespace std;
const int MAXCLI=0;
//Server variables.
bool server_online;
int server_port;
//Client variables.
char clients_chatmsg[200];
char clients_online_users[21][MAXCLI];
int clients_newchatmsg = 0;
bool client_online[MAXCLI];
map<string,int> onlinemap;
int client_timeout[MAXCLI];
// Messages sender.
DWORD __stdcall msgsend(void *p)
{
int sd2=*((int*)p);
while(client_online[sd2]==true)
{
if(clients_newchatmsg==1)
{
send(sd2,clients_chatmsg,strlen(clients_chatmsg),0);
Sleep(2);
clients_newchatmsg=0;
}
else
{
Sleep(2);
}
}
return 0;
}
//Timeout system.
DWORD __stdcall timeout(void *p)
{
int sd2=*((int*)p);
while(1)
{
Sleep(600000);
if(client_timeout[sd2]==1)
{
client_timeout[sd2]=0;
}
else if(client_timeout[sd2]==2)
{
break;
}
else
{
send(sd2,"\r\n#Disconnected due timeout.\r\n",strlen("\r\n#Disconnected due timeout.\r\n"),0);
Sleep(5000);
client_online[sd2]=false;
closesocket(sd2);
sprintf(clients_chatmsg,"\r\n#Server: %s leaved due timeout. \r\n",clients_online_users[sd2]);
clients_newchatmsg=1;
break;
}
}
return 0;
}
DWORD __stdcall client(void *p)
{
int n;
int sd2=*((int*)p);
int socket;
int i;
int x;
char input[5] = "";
char buf[150] = "";
char argu1[120];
char argu2[20];
char argu3[100];
char name[20];
// Setting clients online status, and setting the timeout thread to 1.
client_online[sd2]=true;
client_timeout[sd2]=1;
//Starting the timeout thread.
DWORD id4;
CreateThread(0, 0, timeout, (LPVOID)&sd2, 0, &id4);
//Welcome messages.
send(sd2,"Welcome to Quiw's telnet chat server, enter name: ",strlen("Welcome to Quiw's telnet chat server, enter name: "),0);
//Starting to receive name input.
while(strstr(input,"\n")=='\0')
{
n = recv(sd2, input, sizeof(input),0);
if(strlen(buf)<=20)
{
input[n] = '\0';
strcat(buf,input);
//Backspace system.
if(strcmp(input,"\b")=='\0')
{
buf[strlen(buf)-2] = '\0';
send(sd2," \b",strlen(" \b"),0);
}
//If connection closed wrong, send to closesystem.
else if(strcmp(input,"\0")=='\0')
{
goto client_closeconnection;
}
}
else
{
//If the maximum of 20 is reached, overwrite existing char.
send(sd2,"\b\b",strlen("\b\b"),0);
buf[strlen(buf)-1] = '\0';
}
}
//Setting name = input and removing the \n char.
sprintf(name,"%s",buf);
name[strlen(name)-2] = '\0';
sprintf(clients_online_users[sd2],"%s",name);
onlinemap.insert(make_pair(name,sd2));
//Cleaning up buf and input, to prevent garbage in input system.
sprintf(input,"");
sprintf(buf,"");
sprintf(clients_chatmsg,"%s%s%s","\r\nServer: ",clients_online_users[sd2]," has connected. \r\n");
clients_newchatmsg=1;
//Hello and welcome messages.
send(sd2,"\r\n",strlen("\r\n"),0);
send(sd2,"Hello ",strlen("Hello "),0);
send(sd2,name,strlen(name),0);
send(sd2,", go chatting :) (Type: /help to see commands.)\r\n",strlen(", go chatting :) (Type: /help to see commands.\r\n"),0);
send(sd2,"\r\n----------- Chat ---------- \r\n",strlen("\r\n ----------- Chat ---------- \r\n"),0);
//Starting to receive the chat messages.
DWORD id2;
CreateThread(0, 0, msgsend, (LPVOID)&sd2, 0, &id2);
//The loop where all command inputs comes.
while(client_online[sd2]==true)
{
x=0;
// Resetting the client timeout system.
client_timeout[sd2]=1;
//Sleep 201 sec, to prevent chatmessages to print when cmd are printing.
Sleep(201);
//The prompt.
send(sd2,"cmd: ",strlen("cmd: "),0);
//Starting to receive.
while(strstr(input,"\n")=='\0')
{
n = recv(sd2, input, sizeof(input),0);
if(strlen(buf)<=120)
{
input[n] = '\0';
strcat(buf,input);
//Backspace system.
if(strcmp(input,"\b")=='\0')
{
buf[strlen(buf)-2] = '\0';
send(sd2," \b",strlen(" \b"),0);
}
//If connection closed wrong, send to closesystem.
else if(strcmp(input,"\0")=='\0')
{
closesocket(sd2);
goto client_closeconnection;
}
}
else
{
//If the maximum of 120 is reached, overwrite existing char.
send(sd2,"\b\b",strlen("\b\b"),0);
buf[strlen(buf)-1] = '\0';
}
}
cout << buf;
//Removing \n and cleaning up the chars.
buf[strlen(buf)-2] = '\0';
sprintf(input,"");
//Putting the arguments in variables.
sscanf(buf,"%s %s %s",&argu1,&argu2,&argu3);
//Commands:
if(client_online[sd2]==false)
{
break;
}
//Tell system, uses the arguments.
else if(strstr(argu1,"/tell")==argu1)
{
if (onlinemap[argu2]<=0)
{
send(sd2,"\r\n#system: User is not online. \r\n",strlen("\r\n#system: User is not online. \r\n"),0);
}
else
{
sprintf(buf,"%s",buf+strlen(argu1)+strlen(argu2)+2);
sprintf(argu3,"\r\n%s tells you: %s \r\n",name,buf);
send(onlinemap[argu2],argu3,strlen(argu3),0);
}
}
//quit system.
else if (strstr(buf,"/quit")==buf)
{
send(sd2,"\r\nYou have Disconnected.\r\n",strlen("\r\nYou have Disconnected.\r\n"),0);
closesocket(sd2);
sprintf(clients_chatmsg,"\r\n#server: %s leaved. \r\n",clients_online_users[sd2]);
clients_newchatmsg=1;
goto client_closeconnection;
}
else if (strstr(buf,"/help")==buf)
{
send(sd2,"\r\n/----- Help ------------------\r\n",strlen("\r\n----- Help ------------------\r\n"),0);
send(sd2,"\r\n/tell username messages - Send a private messages. ",strlen("\r\n/tell username messages - Send a private messages. "),0);
send(sd2,"\r\n/help - this message.",strlen("\r\n/help - this message."),0);
send(sd2,"\r\n/quit - logout.\r\n",strlen("\r\n/quit - logout.\r\n"),0);
send(sd2,"\r\n/-----------------------------\r\n",strlen("\r\n-----------------------------\r\n"),0);
send(sd2,"\r\n",strlen("\r\n"),0);
Sleep(100);
}
//Else.
else
{
sprintf(clients_chatmsg,"\r\n%s says: %s\r\n",name,buf);
clients_newchatmsg=1;
}
//Cleaning up buf.
sprintf(buf,"");
}
//Close connection system.
client_closeconnection:
cout << "Client: ?? - "<<clients_online_users[sd2]<<" disconnected \n";
//Cleaning up the name maps.
client_timeout[sd2]=2;
client_online[sd2]=false;
sprintf(clients_online_users[sd2],"\0");
onlinemap.erase(name);
return 0;
}
//The start server part.
DWORD __stdcall startserver(void *p)
{
int sd2[MAXCLI];
int n=0;
int len;
WSADATA WSAData;
WSAStartup(0x0101,&WSAData);
int sd=socket(AF_INET,SOCK_STREAM,0);
if(sd<0)
{
cout << "#Could not create socket: " << strerror(errno) << endl;
}
else
{
cout << "#Socket created succesfull. \n";
}
int status;
struct sockaddr_in local;
struct sockaddr_in remote;
local.sin_family=AF_INET;
local.sin_port = htons(server_port);
local.sin_addr.s_addr = INADDR_ANY;
status=bind(sd,(struct sockaddr *)&local,sizeof(local));
if(status<0)
{
cout << "#Could not bind socket: " << strerror(errno) << endl;
}
else
{
cout << "#Socket binded succesfull. \n";
}
status=listen(sd,5);
if(status<0)
{
cout << "#Could not listen to socket: " << strerror(errno) << endl;
}
else
{
cout << "#Socket listen succesfull. \n";
}
cout << "#Server online. \n";
// Accept loop.
while(server_online == true)
{
sd2[n]=accept(sd,0,0);
if(sd2[n]<0)
{
cout << "#Could not accept socket: " << strerror(errno) << endl;
}
//Starting client thread.
DWORD id;
CreateThread(0, 0, client, (LPVOID)&sd2[n], 0, &id);
// Receiving the IP from client.
len = sizeof(remote);
status=getpeername(sd2[n],(struct sockaddr *)&remote,&len);
if(status<0)
{
printf("Error getting socket address: %s\n",strerror(errno));
}
printf("Client: ID:%d - %d.%d.%d.%d connected\n",sd2[n],remote.sin_addr.s_net,remote.sin_addr.s_host, remote.sin_addr.s_lh,remote.sin_addr.s_impno);
}
//Clean up.
WSACleanup();
cout << "server tråden er stoppet \n";
return 0;
}
int main()
{
int cmd_number;
int sd2[MAXCLI];
char cmd[100];
bool server=true;
cout << "#Quiw's chatserver 1.0 \n";
cout << "----------------------> \n";
cout << "- Type /help for more information. \n\n";
while(server==true)
{
Sleep(1000);
cout << "\r\ncmd: ";
cin.getline(cmd,sizeof(cmd));
if(strstr(cmd,"/startserver")==cmd)
{
if (server_online==true)
{
cout << "\r\n#The server is already running \n";
}
else
{
server_port=atoi((cmd+13));
if (server_port>0)
{
cout << "\r\n#Starting server... \n";
server_online=true;
DWORD id3;
CreateThread(0, 0, startserver, (LPVOID)&sd2,0, &id3);
Sleep(50);
}
else
{
cout << "#Port number is not given \n";
}
}
}
else if(strstr(cmd,"/shutdown")==cmd)
{
(cmd+11);
if (server_online==false)
{
cout << "#There is not a server running \n";
}
else
{
cout << "#shutting down server... \n";
server_online=false;
Sleep(1000);
cout << "#Server offline. \n";
}
}
else if(strstr(cmd,"/whois")==cmd)
{
sprintf(cmd,"%s",(cmd+7));
if (server_online==true)
{
if (onlinemap[cmd]<=0)
{
cout << "User not exist. \n";
}
else
{
cout << "Name: "<< cmd <<" has ID: "<<onlinemap[cmd]<<"\n";
}
}
else
{
cout << "#There is not a server running \n";
}
}
else if(strstr(cmd,"/help")==cmd)
{
cout << "\nHelp info: \n";
cout << "----------------- \n";
cout << "/shutdown - Shutting down the server. \n";
cout << "/startserver port - Start the server at a given port number \n";
cout << "/quit - Shuts down the program \n";
cout << "/stats - Shows starts about running server \n";
cout << "/whois - Who is user \n";
cout << "/help - This message \n";
cout << "/kick - kicks a given user \n";
}
else if(strstr(cmd,"/stats")==cmd)
{
if(server_online==true)
{
cout << "Server online: true\n";
cout << "Server port: "<<server_port<<"\n";
}
else
{
cout << "#The server is not running \n";
}
}
else if(strstr(cmd,"/kick")==cmd)
{
if(server_online==true)
{
cmd_number=atoi((cmd+6));
if (cmd_number>0)
{
send(cmd_number,"\r\n#You got kicked. \r\n",strlen("\r\n#You got kicked. \r\n"),0);
Sleep(3000);
closesocket(cmd_number);
sprintf(clients_chatmsg,"\r\n%s%s%s","\nSystem: ",clients_online_users[cmd_number]," has been kicked. \r\n");
clients_newchatmsg=1;
client_timeout[cmd_number]=2;
client_online[cmd_number]=false;
cout << "#Socket ID: "<<cmd_number<<" has been kicked \n";
}
else
{
cout << "#ID argument is not given \n";
}
}
else
{
cout << "#The server is not running \n";
}
}
else if(strstr(cmd,"/quit")==cmd)
{
(cmd+7);
if(server_online==true)
{
cout << "#Server is already running, are you sure? Y/N \n";
wrongchoice:
cin.getline(cmd,sizeof(cmd));
if(strstr(cmd,"y")==cmd ||(cmd,"Y")==cmd)
{
server_online=false;
cout << "#Server offline. \n";
cout << "#Closing .. \n";
Sleep(1000);
return 0;
}
else if(strstr(cmd,"n")==cmd || (cmd,"N")==cmd)
{
cout << "#Returning back to console .. \n";
}
else
{
cout << "#Unknown choice. \n";
cout << "Please retry, Y/N. \n";
goto wrongchoice;
}
}
else
{
cout << "#Closing .. \n";
Sleep(1000);
return 0;
}
}
else
{
cout << "#Unknown command: '"<<cmd<<"'\n";
}
cout << "\n";
}
return 0;
}
Håber der er nogle som har nogle ideer eller løsninger, på forhånd Tak.