simple instant meesenger code

Sep 25, 2009 at 12:27pm
i really need a big help from you guys!!my codes for our midterm project is still not successful. today(9-19-09) was suppostedly last submission but luckily, our lab teacher moved it to next saturday, 9-26-09. the only thing i understand with this code is the general flow of the codes, i still cant understand the specific implementations. im still not good with the language used because im having a hard time studying it but i really wanna master in(c++). i wish you can help me make myself understand the codes and i also beg for your help to give a hint on how to solve this program.pls help to have a passing mark on this course.

i also wanna ask your suggestion if what other features can i add to this program

problem
our 2nd project in my computer proggramming 2 class is to modify a chatting code and add the following

1. Take a look at the implementation of the .nick <nick> command in talker.cpp. Modify it so that the user can only change his/her current nick to <nick> only if <nick> is not used yet.
2. Modify talker.cpp chat server program to include the following commands:

* .talk <nick> <msg> - this command sends the message <msg> privately to user <nick>.
* .who - displays all currently logged in users.
* .emote <something> - displays <something> next to your nick. For example, if you type,

.emote feels sad.

will display,

<your nick> feels sad.

* .pokes <nick> - displays the following on the screen:

<your nick> pokes <nick>.


Sep 25, 2009 at 12:28pm


the chatting code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
/*
NOTE: This is a basic chat server which allows users to connect to it and be able
to talk in a public chat room. To connect, enter the following at your DOS prompt:

telnet localhost 6789

Do this for each chat client. If you want your classmates to connect to your server
within the laboratory LAN, simply change the macro 'HOST' to the actual IP address
of your network interface. For example, if the IP address of your network interface
is 10.10.7.23, then he/she can connect to your server by entering,

telnet 10.10.7.23 6789

at his/her DOS prompt.
*/

#include <iostream>
#include "PassiveSocket.h" // Include header for passive socket object definition

#define HOST "127.0.0.1" // localhost
#define PORT 6789
#define VERSION 0.01
#define NAME_LEN 11 // including the null character
#define MAX_PACKET 163 // actual message is 160-char long + "\r\n\0"
#define MAX_CLIENTS 100
#define TIME_OUT 5 // in minutes
#define SERVER_FULL "The server is full at the moment. Try again later."

using namespace std;

void bcast(CActiveSocket **clients, int clientCount, char *data, int except);
void sendto(CActiveSocket *client, char *data);
char *new_nick(char names[MAX_CLIENTS][NAME_LEN], int clientCount);

int main()
{
// server socket
CPassiveSocket server;
// client sockets
CActiveSocket *clients[MAX_CLIENTS], *incoming;
// number of clients connected so far
int clientCount;
// nicknames of the connected clients
char names[MAX_CLIENTS][NAME_LEN];
// msg is the message received from client 'i' so far
char msg[MAX_CLIENTS][MAX_PACKET];
// time_of_last_send[i] stores the last time that the client 'i' has sent a message;
// this will be used to impose timeouts on idle clients
long int time_of_last_send[MAX_CLIENTS];
// temporary string variables
char tmpdata[MAX_PACKET+20];
char tmpnick[NAME_LEN];

// Initialize server socket
server.Initialize();

// necessary so our server won't block (i.e. pause and wait) for input
server.SetNonblocking();

// and make it listen at host HOST and port PORT
server.Listen((const uint8 *) HOST, PORT);
cout << "TALKER v" << VERSION << endl;
cout << "Address: " << HOST << " Port: " << PORT << endl;

// we have no clients so far
clientCount = 0;

cout << "Number of clients: " << clientCount << endl;

// while it's not the end of the world
while (1)
{
// accept an incoming connection
if ((incoming = server.Accept()) != NULL)
{
// see if we can accommodate one more client
if (clientCount < MAX_CLIENTS)
{
// take that incoming connection
clients[clientCount] = incoming;

// necessary so our client won't block (i.e. pause and wait) for input
clients[clientCount]->SetNonblocking();

// start with a default nick and
strcpy(names[clientCount], new_nick(names, clientCount));
// an empty message buffer
strcpy(msg[clientCount], "");

cout << names[clientCount] << " has joined." << endl;

// display prompt to client
sprintf(tmpdata, "Welcome %s!\n\r%s> ", names[clientCount], names[clientCount]);
sendto(clients[clientCount], tmpdata);

// inform other clients
sprintf(tmpdata, "\n\r%s has joined.\n\r", names[clientCount]);
bcast(clients, clientCount+1, tmpdata, clientCount);

// we have one more client in
clientCount++;
cout << "Number of clients: " << clientCount << endl;
} // if
else // maximum number of clients reached; reject connection
{
incoming->Send((const uint8 *) SERVER_FULL, strlen(SERVER_FULL));
incoming->Close();
} // else

} // if

// for each client, check if it is sending a message to the server
// concatenate the new message of the client with its previous message if there's any
for (int i=0; i < clientCount; i++)
if (clients[i]->Receive(MAX_PACKET) > 0)
{
// empty tmpdata
strcpy(tmpdata, "");
// now catenate 'tmpdata' with the new message
strncat(tmpdata, (const char *) clients[i]->GetData(), clients[i]->GetBytesReceived());
// and then append it to the previous;
// msg[i] is the message received from client 'i' so far
strcat(msg[i], tmpdata);
}

// now, process the message sent by each client
// we only process a message if it is terminated by "\r\n" (produced by pressing the ENTER key)
// else we accumulate the messages above until it is terminated by "\r\n"
for (int i = 0; i < clientCount; i++)
{
// if the message contains '\n', process it
if (strchr(msg[i],'\n')) {

// but remove first "\r\n" from msg[i] by putting a '\0' before them
msg[i][strlen(msg[i])-2] = '\0';

// see if msg[i] is not empty
if (strlen(msg[i]) > 0)
{
// do the actual processing of the message here:

// any msg[i] which starts with a '.' is considered to be a command
if (msg[i][0] != '.')
{
// output to server console
cout << names[i] << ": " << msg[i] << endl;

// broadcast to the clients
sprintf(tmpdata, "%s: %s\n\r", names[i], msg[i]);
bcast(clients, clientCount, tmpdata, -1);
} else // it's a command!
{
// .nick <nickname> - change nickname command
if (strncmp(msg[i], ".nick ", 6) == 0)
{
// copy new nick which is right after the space after .nick
strcpy(tmpnick, msg[i]+6);
cout << names[i] << " is now known as " << tmpnick << "." << endl;

// broadcast to all the rest of the clients,
sprintf(tmpdata, "\n\r%s is now known as %s.\n\r", names[i], tmpnick);
bcast(clients, clientCount, tmpdata, i);

// now, overwrite the old nick with the new one
strcpy(names[i], tmpnick);
}
else if (strncmp(msg[i], ".quit", 5) == 0)
{
// say 'Bye.' to disconnecting client
sendto(clients[i], "Bye.");

// and then inform the others
sprintf(tmpdata, "\n\r%s is now offline.\n\r", names[i]);
bcast(clients, clientCount, tmpdata, i);

// and finally, close the connection
clients[i]->Close();

cout << names[i] << " is now offline." << endl;


// DELETION OF THE CLIENT FROM THE LIST:
// now, we move all storage starting at client 'i+1'
// to client 'clientCount-1', overwriting client 'i'
for (int j = i; j < clientCount-1; j++)
{
clients[j] = clients[j+1];
strcpy(msg[j], msg[j+1]);
strcpy(names[j], names[j+1]);
}

// less one client
clientCount--;
cout << "Number of clients: " << clientCount << endl;

// finally, restart 'i' to the position where we
// performed the deletion to process the client
// we moved from 'i+1'
i--;

// bypass post processing of 'msg[i]' and
// the display of the '>' prompt below
goto after_deletion;
}
}
}
// after processing the message buffer, empty it!
strcpy(msg[i], "");

// and then display the prompt '>'
sprintf(tmpdata, "%s> ", names[i]);
clients[i]->Send((const uint8*) tmpdata, strlen(tmpdata));


after_deletion:;
} // if
} // for
} // while

// close server socket
server.Close();

return 0;
} // main

// broadcasts 'data' to all clients except 'except'.
// to include sender, call this function with 'except' set to -1.
void bcast(CActiveSocket **clients, int clientCount, char *data, int except)
{
for (int i = 0; i < clientCount; i++)
if (i != except)
clients[i]->Send((const uint8*) data, strlen(data));
}

void sendto(CActiveSocket *client, char *data)
{
client->Send((const uint8*) data, strlen(data));
}

char *new_nick(char names[MAX_CLIENTS][NAME_LEN], int clientCount)
{
char tmpnick1[NAME_LEN], tmpnick2[NAME_LEN];
int unique_nick;
char msg[MAX_CLIENTS][MAX_PACKET];


for (int i = 0; i < MAX_CLIENTS; i++)
{
if (strcpy(tmpnick1, "Guest"))
{
itoa(i, tmpnick2, MAX_CLIENTS);
strcat(tmpnick1, tmpnick2);

unique_nick = 1;
for (int j = 0; j < clientCount; j++)
if (strcmp(tmpnick1, names[j]) == 0)
unique_nick = 0;
if (unique_nick)
return tmpnick1;

else if (strncmp(msg[i], ".who", 4) == 0)
{
//displays all the login users
cout << "This is the list of online users:" << endl;
for (int j=0; j < clientCount; j++)
{
cout << names[j] <<endl;
}
}

}

}

}


END

Last edited on Sep 27, 2009 at 6:31am
Sep 25, 2009 at 6:07pm
Please, please, please use code tags. That's just too much code to try to skim through as raw unformated text.
Topic archived. No new replies allowed.