1 Star 0 Fork 0

chenxfeng/chatting_program

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
该仓库未声明开源许可证文件(LICENSE),使用请关注具体项目描述及其代码上游依赖。
克隆/下载
server_ver4_0.c 28.31 KB
一键复制 编辑 原始数据 按行查看 历史
chenxfeng 提交于 2017-04-25 07:23 . Add files via upload
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830
// Server.cpp : 定义控制台应用程序的入口点。
// g++编译需加入编译选项 -lwsock32
// #include "stdafx.h"
#include <stdlib.h>
#include <stdio.h>
#include <Winsock2.h>
#include <process.h>
#include "conio.h"
#pragma comment(lib, "ws2_32.lib")
#define QLEN 5
#define STRLEN 4096
#define SERVPORT 5400
#define WSVERS MAKEWORD(2, 2)
//#define _WINSOCK_DEPRECATED_NO_WARNINGS
#define USER_NOT_EXISTS 400
#define INCORRECT_PASSWORD 401
#define USER_NOT_FOUND 4040
#define NOT_ONLINE 4041
#define REJECT_CHATTING 4042
#define IS_ONLINE 2000
#define START_CHATTING 2001
#define MAXCLNT 64
#define CLIUSERLEN 8
HANDLE hThread[MAXCLNT]; // cli thread pool
int cln_count = 0;
HANDLE chatRequThread[MAXCLNT]; // thread pool for chatting: request
HANDLE chatDestThread[MAXCLNT]; // thread pool for chatting: destination
int chat_count = 0;
struct SockInfo {
SOCKET sock;
int userId;
} cliSock[MAXCLNT]; // socket pool
struct User {
int valid;
char username[CLIUSERLEN + 1];
char password[CLIUSERLEN + 1];
int online;
int lock; // waiting thread lock
SOCKET sock;
struct sockaddr_in addr;
} CliUser[MAXCLNT]; // user infomation
int group_count = 0;
struct Group {
int userId[MAXCLNT];
int num;
int quitState;
} chatGroup[MAXCLNT];
HANDLE chatGroupThread[MAXCLNT]; // thread for group chatting
int chat_group_count = 0;
unsigned __stdcall send_to_all(void * linksock);
void errExit(const char* errStr, int num = 0) {
printf(errStr, num);
return;
}
void testSend(int messageLen);
void initUser();
void initGroup();
int findUser(char * message);
int userLogIn(SOCKET linksock, struct sockaddr_in addr);
int getSockUserId(SOCKET linksock);
void writeUserListToBuf(char * buf, int num);
void chat(int userID);
void oneToOneChatStart(int reqId, int destId);
unsigned __stdcall sendToOne(void * userID);
void list(SOCKET linksock);
unsigned __stdcall sendToGroup(void * ID);
void groupChat(int userID);
int main(int argc, char **argv) {
initUser();
initGroup();
struct sockaddr_in localSockIn, fromSockIn;
SOCKET masterSock;
WSADATA wsadata;
int addrLen;
char rBuf[STRLEN], wBuf[STRLEN];
int messageLen;
if (WSAStartup(WSVERS, &wsadata) != 0)
errExit("WSAStartup failed\n");
// create socket
masterSock = socket(PF_INET, SOCK_STREAM, 0);
if (masterSock == INVALID_SOCKET) {
errExit("failed socket, error number: %d\n", WSAGetLastError());
}
// server address
localSockIn.sin_family = AF_INET;
localSockIn.sin_port = htons(SERVPORT);
localSockIn.sin_addr.s_addr = htonl(INADDR_ANY);
// binding
if (bind(masterSock, (SOCKADDR*)&localSockIn, sizeof(localSockIn)) == SOCKET_ERROR) {
errExit("bind() failed: %d\n", WSAGetLastError());
}
// listen
if (listen(masterSock, QLEN) == SOCKET_ERROR) {
errExit("listen() failed: %d\n", WSAGetLastError());
}
// client address length
addrLen = sizeof(fromSockIn);
// wait for connection from client...
while (true) {
if (cln_count < MAXCLNT) {
printf("port %d is waiting for connection from %s...\n",
ntohs(localSockIn.sin_port), inet_ntoa(localSockIn.sin_addr));
cliSock[cln_count].sock = accept(masterSock, (SOCKADDR*)&fromSockIn, &addrLen);
if (cliSock[cln_count].sock == INVALID_SOCKET) {
errExit("eccept() failed: %d\n", WSAGetLastError());
}
printf("accept a client whose IP is %s port %d. \n",
inet_ntoa(fromSockIn.sin_addr), ntohs(fromSockIn.sin_port));
// struct sockaddr_in clnAddr;
// int clnAddrLen;
// memset(&clnAddr, 0, sizeof(clnAddr));
// int ret = getpeername(lsock, (struct sockaddr*)&cln_addr, &cln_addr_len);
// the cli log in
int userId = userLogIn(cliSock[cln_count].sock, fromSockIn);
if (userId < 0) {
// log in failed
continue;
}
cliSock[cln_count].userId = userId;
CliUser[userId].lock = 0; // not locked
CliUser[userId].sock = cliSock[cln_count].sock;
// send user list to new cli
memset(wBuf, 0, sizeof(wBuf));
writeUserListToBuf(wBuf, cln_count);
messageLen = send(cliSock[cln_count].sock, wBuf, strlen(wBuf), 0);
testSend(messageLen);
// send to all clis, including latest one
memset(wBuf, 0, sizeof(wBuf));
sprintf(wBuf, "user %s from IP: %s port number: %d log in. \n",
CliUser[userId].username, inet_ntoa(fromSockIn.sin_addr), fromSockIn.sin_port);
for (int i = 0; i <= cln_count; ++i) {
// fputs("Input message: ", stdout);
// fgets(wBuf, STRLEN, stdin);
// scanf_s("%s", wBuf, sizeof(wBuf));
messageLen = send(cliSock[i].sock, wBuf, strlen(wBuf), 0);
testSend(messageLen);
}
// take the socket into thread pool
hThread[cln_count] = (HANDLE)_beginthreadex(NULL, 0, &send_to_all, (void *)&cliSock[cln_count], 0, NULL);
cln_count++;
}
else {
printf("There are too much clis online.\n");
break;
}
}
WaitForMultipleObjects(cln_count, hThread, TRUE, INFINITE);
closesocket(masterSock);
// close thread
for (int i = 0; i < cln_count; i++) {
CloseHandle(hThread[i]);
}
WSACleanup();
return 0;
}
unsigned __stdcall send_to_all(void * linksock) {
int sock_index;
struct sockaddr_in cln_addr;
int cln_addr_len;
char message[STRLEN];
char sendmsg[STRLEN + 100];
SOCKET lsock = *((SOCKET*)linksock);
int recvlen, messageLen;
// get sock_addr
int userId = getSockUserId(lsock);
if (lsock < 0) return 0;
memset(&cln_addr, 0, sizeof(cln_addr));
cln_addr = CliUser[userId].addr;
cln_addr_len = sizeof(cln_addr);
while (true) {
while (CliUser[userId].lock) {
continue;
}
memset(&message, 0, sizeof(message));
recvlen = recv(lsock, message, STRLEN, 0);
if (recvlen == 0 || recvlen == SOCKET_ERROR) {
// force downline
memset(&sendmsg, 0, sizeof(sendmsg));
sprintf(sendmsg, "user %s from IP: %s port: %d log out. \n",
CliUser[userId].username, inet_ntoa(cln_addr.sin_addr), cln_addr.sin_port);
printf("%s", sendmsg);
CliUser[userId].online = 0;
for (int i = 0; i < cln_count; i++) {
if (cliSock[i].sock != lsock) {
messageLen = send(cliSock[i].sock, sendmsg, strlen(sendmsg), 0);
testSend(messageLen);
}
else
sock_index = i;
}
break;
}
else if (recvlen > 0) {
message[recvlen] = '\0';
if (strncmp(message, "quit", 5) == 0) {
// quit
memset(&sendmsg, 0, sizeof(sendmsg));
sprintf(sendmsg, "user %s from IP: %s port: %d log out. \n",
CliUser[userId].username, inet_ntoa(cln_addr.sin_addr), cln_addr.sin_port);
printf("%s", sendmsg);
CliUser[userId].online = 0;
// inform all users
for (int i = 0; i < cln_count; i++) {
if (cliSock[i].sock != lsock) {
messageLen = send(cliSock[i].sock, sendmsg, strlen(sendmsg), 0);
testSend(messageLen);
}
else
sock_index = i;
}
break;
}
else if (!CliUser[userId].lock && strncmp(message, "chat", 5) == 0) {
// chat request
chat(userId);
}
else if (strncmp(message, "list", 5) == 0) {
list(lsock);
}
/* else {
// normal message
memset(&sendmsg, 0, sizeof(sendmsg));
sprintf(sendmsg, "user %s from IP: %s port: %d say: %s",
CliUser[userId].username, inet_ntoa(cln_addr.sin_addr), cln_addr.sin_port, message);
printf("%s", sendmsg);
// send to all users
for (int i = 0; i < cln_count; i++) {
messageLen = send(cliSock[i].sock, sendmsg, strlen(sendmsg), 0);
testSend(messageLen);
}
} */
}
}
// move the sockets behind the log-out one forward
for (int i = sock_index; i < cln_count - 1; i++) {
cliSock[i].sock = cliSock[i + 1].sock;
cliSock[i].userId = cliSock[i + 1].userId;
}
cln_count--;
closesocket(lsock);
return 0;
}
void testSend(int messageLen) {
switch (messageLen) {
case SOCKET_ERROR: errExit("send() failed: %d\n", WSAGetLastError()); break;
case 0: errExit("send() failed: %d\n", WSAGetLastError()); break;
default: break;//printf("send() successfully. \n", messageLen);
}
return;
}
void initUser() {
CliUser[0].valid = 1;
strncpy(CliUser[0].username, "test", 5);
strncpy(CliUser[0].password, "test", 5);
CliUser[0].online = 0;
CliUser[1].valid = 1;
strncpy(CliUser[1].username, "chenxf", 7);
strncpy(CliUser[1].password, "chenxf", 7);
CliUser[1].online = 0;
CliUser[2].valid = 1;
strncpy(CliUser[2].username, "remote", 7);
strncpy(CliUser[2].password, "remote", 7);
CliUser[2].online = 0;
CliUser[3].valid = 1;
strncpy(CliUser[3].username, "remote", 7);
strncpy(CliUser[3].password, "remote", 7);
CliUser[3].online = 0;
CliUser[4].valid = 1;
strncpy(CliUser[4].username, "cafe", 5);
strncpy(CliUser[4].password, "cafe", 5);
CliUser[4].online = 0;
CliUser[5].valid = 1;
strncpy(CliUser[5].username, "alpha", 6);
strncpy(CliUser[5].password, "alpha", 6);
CliUser[5].online = 0;
CliUser[6].valid = 1;
strncpy(CliUser[6].username, "beta", 5);
strncpy(CliUser[6].password, "beta", 5);
CliUser[6].online = 0;
CliUser[7].valid = 1;
strncpy(CliUser[7].username, "gamma", 6);
strncpy(CliUser[7].password, "gamma", 6);
CliUser[7].online = 0;
for (int i = 8; i < MAXCLNT; ++i) {
CliUser[i].valid = 0;
}
return;
}
int findUser(char * message) {
for (int i = 0; i < MAXCLNT; ++i) {
if (CliUser[i].valid) {
if (strstr(message, CliUser[i].username) != NULL)
return i;
}
}
return MAXCLNT + 1;
}
int userLogIn(SOCKET linksock, struct sockaddr_in addr) {
SOCKET lsock = linksock;
char message[STRLEN];
char sendmsg[STRLEN];
struct sockaddr_in cln_addr = addr;
int cln_addr_len = sizeof(cln_addr);
int messageLen;
// resv username
memset(&message, 0, sizeof(message));
int recvlen = recv(lsock, message, sizeof(message), 0);
if (recvlen == 0 || recvlen == SOCKET_ERROR) {
memset(&sendmsg, 0, sizeof(sendmsg));
sprintf(sendmsg, "user from IP: %s port: %d log in failed. \n",
inet_ntoa(cln_addr.sin_addr), cln_addr.sin_port);
printf("%s", sendmsg);
return -1;
}
else if (recvlen > 0) {
// get username
// message[recvlen] = '\0';
int userId = findUser(message); // maybe unsafe
if (userId < MAXCLNT) {
// find the user, request for password
memset(&sendmsg, 0, sizeof(sendmsg));
sprintf(sendmsg, "user %s from IP: %s port: %d. Please Input password: ",
CliUser[userId].username, inet_ntoa(cln_addr.sin_addr), cln_addr.sin_port);
messageLen = send(lsock, sendmsg, strlen(sendmsg), 0);
testSend(messageLen);
// get password
memset(&message, 0, sizeof(message));
int pwdLen = recv(lsock, message, sizeof(message), 0);
if (pwdLen == 0 || pwdLen == SOCKET_ERROR) {
// get password error
memset(&sendmsg, 0, sizeof(sendmsg));
sprintf(sendmsg, "user %s from IP: %s port: %d log in failed: get-password error. \n",
CliUser[userId].username, inet_ntoa(cln_addr.sin_addr), cln_addr.sin_port);
printf("%s", sendmsg);
return -1;
}
else if (pwdLen > 0) {
// got password, confirm it
// message[pwdLen] = '\0';
if (strstr(message, CliUser[userId].password) != NULL) {
// correct password
memset(&sendmsg, 0, sizeof(sendmsg));
sprintf(sendmsg, "user %s from IP: %s port: %d log in. \n",
CliUser[userId].username, inet_ntoa(cln_addr.sin_addr), cln_addr.sin_port);
printf("%s", sendmsg);
// log in success, reply the user
messageLen = send(lsock, sendmsg, strlen(sendmsg), 0);
testSend(messageLen);
// change user status
CliUser[userId].online = 1;
CliUser[userId].addr.sin_family = AF_INET;
CliUser[userId].addr.sin_addr = cln_addr.sin_addr;
CliUser[userId].addr.sin_port = cln_addr.sin_port;
return userId;
}
else {
// wrong passeord
memset(&sendmsg, 0, sizeof(sendmsg));
sprintf(sendmsg, "incorrect password: user %s from IP: %s port: %d log in failed. \n",
CliUser[userId].username, inet_ntoa(cln_addr.sin_addr), cln_addr.sin_port);
printf("%s", sendmsg);
// reply INCORRECT_PASSWORD(401)
memset(&sendmsg, 0, sizeof(sendmsg));
sprintf(sendmsg, "%d", INCORRECT_PASSWORD);
messageLen = send(lsock, sendmsg, strlen(sendmsg), 0);
testSend(messageLen);
return -1;
}
}
}
else {
// username not found
memset(&sendmsg, 0, sizeof(sendmsg));
sprintf(sendmsg, "user not exists: user %s from IP: %s port: %d log in failed. \n",
message, inet_ntoa(cln_addr.sin_addr), cln_addr.sin_port);
printf("%s", sendmsg);
// reply USER_NOT_EXISTS(400)
memset(&sendmsg, 0, sizeof(sendmsg));
sprintf(sendmsg, "%d", USER_NOT_EXISTS);
messageLen = send(lsock, sendmsg, strlen(sendmsg), 0);
testSend(messageLen);
return -1;
}
}
return -1;
}
int getSockUserId(SOCKET linksock) {
for (int i = 0; i < MAXCLNT; ++i) {
if (linksock == cliSock[i].sock)
return cliSock[i].userId;
}
return -1;
}
void writeUserListToBuf(char * buf, int num) {
strcpy(buf, "online user list: \n");
int i;
for (i = 0; i < num; ++i) {
if (CliUser[cliSock[i].userId].online) {
strncat(buf, CliUser[cliSock[i].userId].username, CLIUSERLEN);
strcat(buf, "\n");
}
}
char iToStr[4];
sprintf(iToStr, "%d", i);
strcat(buf, iToStr);
strcat(buf, " in total. \n");
return;
}
void chat(int userID) {
int userId = userID;
SOCKET lsock = CliUser[userId].sock;
char wBuf[STRLEN];
char rBuf[STRLEN];
int messageLen;
int recvlen;
// block recv thread in cli
memset(wBuf, 0, sizeof(wBuf));
sprintf(wBuf, "If you do want to chat, ");
messageLen = send(lsock, wBuf, strlen(wBuf), 0);
testSend(messageLen);
// ask which chatting: one-to-one or one-to-more
memset(wBuf, 0, sizeof(wBuf));
sprintf(wBuf, "Send 'one' to start one-to-one chatting or 'group' to start more-to-more chatting : ");
messageLen = send(lsock, wBuf, strlen(wBuf), 0);
testSend(messageLen);
memset(rBuf, 0, sizeof(rBuf));
recvlen = recv(lsock, rBuf, sizeof(rBuf), 0);
if (recvlen == 0 || recvlen == SOCKET_ERROR) {
printf("start chatting failed: choice not received. \n");
return;
}
else if (recvlen > 0) {
rBuf[recvlen] = '\0';
if (strstr(rBuf, "one") != NULL) {
// one-to-one chatting
// request for who it'll chatting with
memset(wBuf, 0, sizeof(wBuf));
sprintf(wBuf, "send the user's name you'll chat with: ");
messageLen = send(lsock, wBuf, strlen(wBuf), 0);
testSend(messageLen);
// got destination username
memset(rBuf, 0, sizeof(rBuf));
recvlen = recv(lsock, rBuf, sizeof(rBuf), 0);
rBuf[recvlen - 1] = '\0';
if (recvlen == 0 || recvlen == SOCKET_ERROR) {
printf("start chatting failed: dest user not received. \n");
return;
}
else if (recvlen > 0) {
// find the user
rBuf[recvlen] = '\0';
int destUserId = findUser(rBuf);
if (destUserId > MAXCLNT) {
// user not found
memset(wBuf, 0, sizeof(wBuf));
sprintf(wBuf, "%d", USER_NOT_FOUND);
messageLen = send(lsock, wBuf, strlen(wBuf), 0);
testSend(messageLen);
printf("user %s is not found. \n", rBuf);
return;
}
if (CliUser[destUserId].online) {
// destination user is online
memset(wBuf, 0, sizeof(wBuf));
sprintf(wBuf, "%d", IS_ONLINE);
messageLen = send(lsock, wBuf, strlen(wBuf), 0);
testSend(messageLen);
printf("user %s is online. \n", rBuf);
// begin chatting forward
CliUser[destUserId].lock = 1; // locked
oneToOneChatStart(userId, destUserId);
CliUser[destUserId].lock = 0; // unlocked
return;
}
else {
// destination user isn't online
memset(wBuf, 0, sizeof(wBuf));
sprintf(wBuf, "%d", NOT_ONLINE);
messageLen = send(lsock, wBuf, strlen(wBuf), 0);
testSend(messageLen);
printf("user %s isn't online. \n", rBuf);
return;
}
}
}
else if (strstr(rBuf, "group") != NULL) {
// more-to-more chatting
groupChat(userId);
}
}
return;
}
void oneToOneChatStart(int reqId, int destId) {
char rBuf[STRLEN];
char wBuf[STRLEN];
SOCKET reqSock = CliUser[reqId].sock;
SOCKET destSock = CliUser[destId].sock;
int messageLen;
int recvlen;
memset(wBuf, 0, sizeof(wBuf));
sprintf(wBuf, "user %s want to chat with you. Send 'chat confirm' to start it or 'chat reject' instead. \n",
CliUser[reqId].username);
messageLen = send(destSock, wBuf, strlen(wBuf), 0);
testSend(messageLen);
memset(rBuf, 0, sizeof(rBuf));
recvlen = recv(destSock, rBuf, sizeof(rBuf), 0);
if (recvlen == 0 || recvlen == SOCKET_ERROR) {
printf("error in starting chatting. \n");
return;
}
else if (recvlen > 0) {
if (strstr(rBuf, "chat confirm") != NULL) {
// tell req user that chat starting
memset(wBuf, 0, sizeof(wBuf));
sprintf(wBuf, "%d", START_CHATTING);
messageLen = send(reqSock, wBuf, strlen(wBuf), 0);
testSend(messageLen);
printf("%s begin chat with %s...\n", CliUser[reqId].username,
CliUser[destId].username);
// start two thread to forward message
int chatId = chat_count;
int id1[2], id2[2];
id1[0] = reqId; id1[1] = destId;
id2[0] = destId; id2[1] = reqId;
chatRequThread[chat_count] = (HANDLE)_beginthreadex(NULL, 0, &sendToOne, (void *)&id1, 0, NULL);
chatDestThread[chat_count] = (HANDLE)_beginthreadex(NULL, 0, &sendToOne, (void *)&id2, 0, NULL);
chat_count++;
WaitForSingleObject(chatRequThread[chatId], INFINITE);
WaitForSingleObject(chatDestThread[chatId], INFINITE);
// end chatting
// move the thread behind the log-out one forward
CloseHandle(chatRequThread[chatId]);
CloseHandle(chatDestThread[chatId]);
for (int i = chatId; i < chat_count - 1; i++) {
chatRequThread[i] = chatRequThread[i + 1];
chatDestThread[i] = chatDestThread[i + 1];
}
chat_count--;
return;
}
else {
// tell req user that chat reject
memset(wBuf, 0, sizeof(wBuf));
sprintf(wBuf, "%d", REJECT_CHATTING);
messageLen = send(reqSock, wBuf, strlen(wBuf), 0);
testSend(messageLen);
return;
}
}
return;
}
unsigned __stdcall sendToOne(void * userID) {
int userIdRecv = ((int*)userID)[0];
int userIdSend = ((int*)userID)[1];
char recvUserName[CLIUSERLEN + 1];
char sendUserName[CLIUSERLEN + 1];
strncpy(recvUserName, CliUser[userIdRecv].username, strlen(CliUser[userIdRecv].username) + 1);
strncpy(sendUserName, CliUser[userIdSend].username, strlen(CliUser[userIdSend].username) + 1);
SOCKET recvSock = CliUser[userIdRecv].sock;
SOCKET sendSock = CliUser[userIdSend].sock;
char message[STRLEN];
char sendmsg[STRLEN];
int recvlen, messageLen;
while (true) {
memset(&message, 0, sizeof(message));
recvlen = recv(recvSock, message, sizeof(message), 0);
if (recvlen == 0 || recvlen == SOCKET_ERROR) {
memset(&sendmsg, 0, sizeof(sendmsg));
sprintf(sendmsg, "user %s leave chatting %s & %s. \n",
recvUserName, recvUserName, sendUserName);
printf("%s", sendmsg);
messageLen = send(sendSock, sendmsg, strlen(sendmsg), 0);
testSend(messageLen);
// chatting end
break;
}
else if (recvlen > 0) {
message[recvlen] = '\0';
if (strstr(message, "quit") != NULL) {
// quit
memset(&sendmsg, 0, sizeof(sendmsg));
sprintf(sendmsg, "user %s leave chatting %s : %s. \n",
recvUserName, recvUserName, sendUserName);
printf("%s", sendmsg);
messageLen = send(sendSock, sendmsg, strlen(sendmsg), 0);
testSend(messageLen);
return 1;
}
else {
// normal message
memset(&sendmsg, 0, sizeof(sendmsg));
sprintf(sendmsg, "%s: %s", recvUserName, message);
// printf("%s", sendmsg);
messageLen = send(sendSock, sendmsg, strlen(sendmsg), 0);
testSend(messageLen);
}
}
}
return 1;
}
void list(SOCKET linksock) {
SOCKET lsock = linksock;
char wBuf[STRLEN];
int messageLen;
// send all online user
memset(wBuf, 0, sizeof(wBuf));
writeUserListToBuf(wBuf, cln_count);
messageLen = send(lsock, wBuf, strlen(wBuf), 0);
testSend(messageLen);
return;
}
void initGroup() {
for (int i = 0; i < MAXCLNT; ++i) {
chatGroup[i].num = 0;
}
}
void groupChat(int userID) {
int userId = userID;
SOCKET lsock = CliUser[userId].sock;
char wBuf[STRLEN];
char rBuf[STRLEN];
int messageLen;
int recvlen;
int gCount = group_count;
int id[2];
id[1] = gCount;
group_count++;
// set the group owner
chatGroup[gCount].userId[chatGroup[gCount].num] = userId;
chatGroup[gCount].num++;
chatGroup[gCount].quitState = 1;
memset(wBuf, 0, sizeof(wBuf));
sprintf(wBuf, "Please input group member(one in a line, end with '.'):\n");
printf("%s", wBuf);
messageLen = send(lsock, wBuf, strlen(wBuf), 0);
testSend(messageLen);
// recv group members' names
memset(rBuf, 0, sizeof(rBuf));
recvlen = recv(lsock, rBuf, sizeof(rBuf), 0);
int cnt = 0;
while (recvlen != 0 && recvlen != SOCKET_ERROR && strncmp(rBuf, ".", 1) != 0) {
rBuf[recvlen - 1] = '\0';
printf("%s, ", rBuf);
id[0] = findUser(rBuf);
if (id[0] < MAXCLNT && !CliUser[id[0]].lock) {
chatGroup[gCount].userId[chatGroup[gCount].num] = id[0];
CliUser[id[0]].lock = 1;
chatGroup[gCount].num++;
}
id[1] = gCount;
chatGroupThread[cnt++] = (HANDLE)_beginthreadex(NULL, 0, &sendToGroup, (void *)&id, 0, NULL);
recvlen = recv(lsock, rBuf, sizeof(rBuf), 0);
}
// notice group members
memset(wBuf, 0, sizeof(wBuf));
sprintf(wBuf, "%s invite you to join a group, reply 'group' to start: ",
CliUser[userId].username);
for (int i = 1; i < chatGroup[gCount].num; ++i) {
messageLen = send(CliUser[chatGroup[gCount].userId[i]].sock, wBuf, strlen(wBuf), 0);
testSend(messageLen);
}
// group-chatting begin
id[0] = userId;
id[1] = gCount;
chatGroupThread[cnt++] = (HANDLE)_beginthreadex(NULL, 0, &sendToGroup, (void *)id, 0, NULL);
WaitForMultipleObjects(chatGroup[gCount].num, chatGroupThread, TRUE, INFINITE);
// close thread
for (int i = 0; i < chatGroup[gCount].num; i++) {
CloseHandle(chatGroupThread[i]);
}
// unlock
for (int i = 1; i < chatGroup[gCount].num; ++i) {
CliUser[chatGroup[gCount].userId[i]].lock = 0;
}
chat_group_count = 0;
chatGroup[gCount].num = 0;
group_count--;
return;
}
unsigned __stdcall sendToGroup(void * ID) {
int userId = ((int*)ID)[0];
int gCount = ((int*)ID)[1];
SOCKET lsock = CliUser[userId].sock;
char rBuf[STRLEN];
char wBuf[STRLEN];
int recvlen;
int messageLen;
printf("%d in %d group chat begin\n", userId, gCount);
while (true) {
memset(rBuf, 0, sizeof(rBuf));
recvlen = recv(lsock, rBuf, sizeof(rBuf), 0);
if (recvlen == 0 || recvlen == SOCKET_ERROR) {
printf("group chat error.\n");
return 1;
}
else {
rBuf[recvlen] = '\0';
if (strncmp(rBuf, "quit group\n", 12) == 0) {
printf("%s quit group chatting.\n", CliUser[userId].username);
if (chatGroup[gCount].quitState) {
memset(wBuf, 0, sizeof(wBuf));
sprintf(wBuf, "quit group");
for (int i = 0; i < chatGroup[gCount].num; ++i) {
messageLen = send(CliUser[chatGroup[gCount].userId[i]].sock, wBuf, strlen(wBuf), 0);
testSend(messageLen);
}
// end group chatting
chatGroup[gCount].quitState = 0;
// group owner
memset(wBuf, 0, sizeof(wBuf));
sprintf(wBuf, "send 'quit group confirm' to leave group: ");
messageLen = send(CliUser[chatGroup[gCount].userId[0]].sock, wBuf, strlen(wBuf), 0);
testSend(messageLen);
}
return 0;
}
memset(wBuf, 0, sizeof(wBuf));
sprintf(wBuf, "%s: %s", CliUser[userId].username, rBuf);
printf("%s", wBuf);
// send to group
for (int i = 0; i < chatGroup[gCount].num; ++i) {
messageLen = send(CliUser[chatGroup[gCount].userId[i]].sock, wBuf, strlen(wBuf), 0);
testSend(messageLen);
}
}
}
return 0;
}
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
1
https://gitee.com/chenxfeng/chatting_program.git
git@gitee.com:chenxfeng/chatting_program.git
chenxfeng
chatting_program
chatting_program
master

搜索帮助

23e8dbc6 1850385 7e0993f3 1850385