turn pCur->sClient;
}
return INVALID_SOCKET;
}
/*
* function 根据SOCKET查找指定客户端
* param client是指定客户端的套接字
* return 返回一个pClient表示查找成功,返回NULL表示无此用户
*/
pClient FindClient(SOCKET client)
{
//从头遍历,一个个比较
pClient pCur = head;
while (pCur = pCur->next)
{
if (pCur->sClient == client)
return pCur;
}
return NULL;
}
/*
* function 计算客户端连接数
* param client表示一个客户端对象
* return 返回连接数
*/
int CountCon()
{
int iCount = 0;
pClient pCur = head;
while (pCur = pCur->next)
iCount++;
return iCount;
}
/*
* function 清空链表
* return 无返回值
*/
void ClearClient()
{
pClient pCur = head->next;
pClient pPre = head;
while (pCur)
{
//head->1->2->3->4,先删除1,head->2,然后free 1
pClient p = pCur;
pPre->next = p->next;
free(p);
pCur = pPre->next;
}
}
/*
* function 检查连接状态并关闭一个连接
* return 返回值
*/
void CheckConnection()
{
pClient pclient = GetHeadNode();
while (pclient = pclient->next)
{
if (send(pclient->sClient, "", sizeof(""), 0) == SOCKET_ERROR)
{
if (pclient->sClient != 0)
{
printf("Disconnect from IP: %s,UserName: %s\n", pclient->IP, pclient->userName);
char error[128] = { 0 }; //发送下线消息给发消息的人
sprintf(error, "The %s was downline.\n", pclient->userName);
send(FindClient(pclient->ChatName), error, sizeof(error), 0);
closesocket(pclient->sClient); //这里简单的判断:若发送消息失败,则认为连接中断(其原因有多种),关闭该套接字
RemoveClient(pclient->flag);
break;
}
}
}
}
/*
* function 指定发送给哪个客户端
* param FromName,发信人
* param ToName, 收信人
* param data, 发送的消息
*/
void SendData(char* FromName, char* ToName, char* data)
{
SOCKET client = FindClient(ToName); //查找是否有此用户
char error[128] = { 0 };
int ret = 0;
if (client != INVALID_SOCKET && strlen(data) != 0)
{
char buf[128] = { 0 };
sprintf(buf, "%s: %s", FromName, data); //添加发送消息的用户名
ret = send(client, buf, sizeof(buf), 0);
}
else//发送错误消息给发消息的人
{
if(client == INVALID_SOCKET)
sprintf(error, "The %s was downline.\n", ToName);
else
sprintf(error, "Send to %s message not allow empty, Please try again!\n", ToName);
send(FindClient(FromName), error, sizeof(error), 0);
}
if (ret == SOCKET_ERROR)//发送下线消息给发消息的人
{
sprintf(error, "The %s was downline.\n", ToName);
send(FindClient(FromName), error, sizeof(error), 0);
}
}
server cpp:
/*
#include
#include
#include
#include "ClientLinkList.h" #pragma comment(lib,"ws2_32.lib") SOCKET g_ServerSocket = INVALID_SOCKET; //服务端套接字 SOCKADDR_IN g_ClientAddr = { 0 }; //客户端地址 int g_iClientAddrLen = sizeof(g_ClientAddr); typedef struct _Send { char FromName[16]; char ToName[16]; char data[128]; }Send,*pSend; //发送数据线程 unsigned __stdcall ThreadSend(void* param) { pSend psend = (pSend)param; //转换为Send类型 SendData(psend->FromName, psend->ToName, psend->data); //发送数据 return 0; } //接受数据 unsigned __stdcall ThreadRecv(void* param) { int ret = 0; while (1) { pClient pclient = (pClient)param; if (!pclient) return 1; ret = recv(pclient->sClient, pclient->buf, sizeof(pclient->buf), 0); if (ret == SOCKET_ERROR) return 1; if (pclient->buf[0] == '#' && pclient->buf[1] != '#') //#表示用户要指定另一个用户进行聊天 { SOCKET socket = FindClient(&pclient->buf[1]); //验证一下客户是否存在 if (socket != INVALID_SOCKET) { pClient c = (pClient)malloc(sizeof(_Client)); c = FindClient(socket); //只要改变ChatName,发送消息的时候就会自动发给指定的用户了 memset(pclient->ChatName, 0, sizeof(pclient->ChatName)); memcpy(pcl |