1 Star 0 Fork 0

chenxfeng/chatting_program

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
该仓库未声明开源许可证文件(LICENSE),使用请关注具体项目描述及其代码上游依赖。
克隆/下载
server_ver1_0.c 11.11 KB
一键复制 编辑 原始数据 按行查看 历史
chenxfeng 提交于 2017-04-23 20:31 . Add files via upload
// Server.cpp : 定义控制台应用程序的入口点。
//
#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 MAXCLNT 64
#define CLIUSERLEN 8
HANDLE hThread[MAXCLNT];
int cln_count = 0;
struct SockInfo {
SOCKET sock;
int userId;
} cliSock[MAXCLNT];
struct User {
int valid;
char username[CLIUSERLEN + 1];
char password[CLIUSERLEN + 1];
int online;
struct sockaddr_in addr;
} CliUser[MAXCLNT];
unsigned __stdcall send_to_all(void * linksock);
void errExit(const char* errStr, int num = 0) {
printf(errStr, num);
return;
}
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;
for (int i = 3; 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;
}
int main(int argc, char **argv) {
initUser();
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;
// 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);
printf("%s", wBuf);
// 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;
while (true) {
memset(&message, 0, sizeof(message));
recvlen = recv(lsock, message, STRLEN, 0);
// get sock_addr
int userId = getSockUserId(lsock);
if (lsock < 0) break;
memset(&cln_addr, 0, sizeof(cln_addr));
cln_addr = CliUser[userId].addr;
cln_addr_len = sizeof(cln_addr);
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 (strstr(message, "quit") != NULL) {
// 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 {
// 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;
}
马建仓 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