/*
模拟用户进入聊天室
1,S接受所有C的连接
2,C向S连接后,把自己的ID(学号)通过TCP发送给S端
3,S向C返回已进入聊天室的所有ID
4,S把新用户ID通知其他用户
5,结束
*/
#include "iostream"
#include <winsock2.h>
#include <windows.h>
#include <process.h>
#pragma comment(lib,"ws2_32.lib")
#pragma warning(disable : 4996)
#pragma warning(disable : 4995)
using namespace std;
#define Const_BufLength 1024
#define MAX_THREAD_LEGTH 64
#define Const_Port 12345
BOOL InitSocket(void);
WSADATA wsaData;
sockaddr_in SerAdd,CliAdd;
SOCKET m_socket,AcceptSocket;
unsigned threadID[MAX_THREAD_LEGTH]={0};
HANDLE hThread[MAX_THREAD_LEGTH];
static unsigned threadCount=0;
class CStudent
{
public:
CStudent()
{
memset(StudentID,0,10);
memset(IP,0,20);
StudentThread=0;
Port=0;
}
char StudentID[10];
int StudentThread;
char IP[20];
int Port;
};
CStudent Student[MAX_THREAD_LEGTH];
BOOL ThreadEnable[MAX_THREAD_LEGTH];
BOOL StudentEnable[MAX_THREAD_LEGTH];
struct RECVPARAM
{
SOCKET sock;
CStudent StudentTemp;
};
unsigned __stdcall RecvProc(LPVOID lpParameter)
{
threadCount++;
BOOL flag=FALSE;
int iLength=sizeof(CliAdd);
char strSendMsg[Const_BufLength];
char strRecvMsg[Const_BufLength];
SOCKET AcceptSocket=((RECVPARAM*)lpParameter)->sock;
CStudent StudentTemp=((RECVPARAM*)lpParameter)->StudentTemp;
memset(strSendMsg,0,sizeof(strSendMsg));
strcpy(strSendMsg,"聊天室已在的用户:\n");
for(int i=0;i<MAX_THREAD_LEGTH;i++)
{
if(StudentEnable[i]==TRUE)
{
char buf[20]={0};
strcpy(buf,Student[i].IP);
strcat(strSendMsg,buf);
sprintf(buf," :%d ",Student[i].Port);
strcat(strSendMsg,buf);
strcpy(buf,Student[i].StudentID);
strcat(strSendMsg,buf);
sprintf(buf," 线程号为:%d\n",Student[i].StudentThread);
strcat(strSendMsg,buf);
flag=TRUE;
}
}
if(flag==FALSE)
strcpy(strSendMsg,"聊天室内没有用户:\n");
int retval=send(AcceptSocket,strSendMsg,sizeof(strSendMsg),0);
if(retval==SOCKET_ERROR)
{
cout<<"发送失败,错误ID为:"<<WSAGetLastError()<<endl;
threadCount--;
closesocket(AcceptSocket);
_endthreadex(0);
return -1;
}
else
{
cout<<"正在等待接收该用户的学号:"<<endl;
}
////////////////////////////////////接收学号
memset(strRecvMsg,0,sizeof(strRecvMsg));
retval=recv(AcceptSocket,strRecvMsg,sizeof(strRecvMsg),0);
if(retval==SOCKET_ERROR)
{
cout<<"该线程接受失败,错误ID为:"<<WSAGetLastError()<<endl;
threadCount--;
closesocket(AcceptSocket);
delete lpParameter;
_endthreadex(0);
return -1;
}
else if(strcmp(strRecvMsg,"exit")==0)
{
cout<<"该线程已退出"<<endl;
ThreadEnable[StudentTemp.StudentThread]=FALSE;
StudentEnable[StudentTemp.StudentThread]=FALSE;
threadCount--;
closesocket(AcceptSocket);
delete lpParameter;
_endthreadex(0);
return -1;
}
else
{
cout<<"学号为"<<strRecvMsg<<"已经注册"<<endl;
strcpy(StudentTemp.StudentID,strRecvMsg);
Student[StudentTemp.StudentThread]=StudentTemp;
StudentEnable[StudentTemp.StudentThread]=TRUE;
}
/////////////////////////////////
while(1)
{
cout<<"等待该学号"<<StudentTemp.StudentID<<"回应"<<endl;
memset(strRecvMsg,0,sizeof(strRecvMsg));
retval=recv(AcceptSocket,strRecvMsg,sizeof(strRecvMsg),0);
if(retval==SOCKET_ERROR)
{
cout<<"学号为:"<<StudentTemp.StudentID<<"接受失败,错误ID为:"<<WSAGetLastError()<<endl;
break;
}
else if(strcmp(strRecvMsg,"exit")==0)
{
cout<<"学号为:"<<StudentTemp.StudentID<<"已经下线"<<endl;
ThreadEnable[StudentTemp.StudentThread]=FALSE;
StudentEnable[StudentTemp.StudentThread]=FALSE;
break;
}
else
{
cout<<strRecvMsg<<endl;
}
}
threadCount--;
closesocket(AcceptSocket);
delete lpParameter;
_endthreadex(0);
return 0;
}
int main()
{
if(!InitSocket())
{
cout<<"套接字初始化出错,即将退出"<<endl;
WSACleanup();
system("pause");
return -1;
}
if(listen(m_socket,SOMAXCONN)==SOCKET_ERROR)
{
cout<<"监听失败,错误ID为:"<<WSAGetLastError()<<endl;
return -1;
}
for(int i=0;i<MAX_THREAD_LEGTH;i++)
{
ThreadEnable[i]=FALSE;
StudentEnable[i]=FALSE;
}
int iLength=sizeof(CliAdd);
int retval;
char strSendMsg[Const_BufLength];
char strRecvMsg[Const_BufLength];
while(TRUE)
{
cout<<"等待客户回应"<<endl;
AcceptSocket=accept(m_socket,(SOCKADDR*)&CliAdd,&iLength);
if(AcceptSocket==INVALID_SOCKET)
{
cout<<"接受失败,错误ID为:"<<WSAGetLastError()<<endl;
return -1;
}
else
{
int i;
for(i=0;i<MAX_THREAD_LEGTH;i++)
{
if(ThreadEnable[i]==FALSE)
break;
}
ThreadEnable[i]=TRUE;
CStudent StudentTemp;
StudentTemp.StudentThread=i;
StudentTemp.Port=ntohs(CliAdd.sin_port);
strcpy(StudentTemp.IP,inet_ntoa(CliAdd.sin_addr));
cout<<"IP:"<<StudentTemp.IP<<"\t端口:"<<StudentTemp.Port<<"已经连接"<<endl;
RECVPARAM *pRecvParam=new RECVPARAM;
pRecvParam->StudentTemp=StudentTemp;
pRecvParam->sock=AcceptSocket;
//hThread=CreateThread(NULL,0,RecvProc,(LPVOID)pRecvParam,0,NULL);
hThread[i] = (HANDLE)_beginthreadex( NULL, 0, &RecvProc,(LPVOID)pRecvParam, 0, (unsigned*)&i);
}
}
WaitForMultipleObjects(threadCount, hThread, TRUE, INFINITE);
for(int i=0;i<MAX_THREAD_LEGTH;i++)
CloseHandle(hThread);
closesocket(m_socket);
WSACleanup();
return 0;
}
BOOL InitSocket(void)
{
if(WSAStartup(MAKEWORD(2,2),&wsaData)!=0)
{
cout<<"加载winsock失败,错误ID为:"<<WSAGetLastError()<<endl;
return FALSE;
}
m_socket=socket(AF_INET,SOCK_STREAM,0);
if(INVALID_SOCKET==m_socket)
{
cout<<"套接字创建失败!错误ID为:"<<WSAGetLastError()<<endl;
return FALSE;
}
SerAdd.sin_family=AF_INET;
SerAdd.sin_port=htons(Const_Port);
SerAdd.sin_addr.S_un.S_addr=htonl(INADDR_ANY);
int retval;
retval=bind(m_socket,(SOCKADDR*)&SerAdd,sizeof(SOCKADDR));
if(SOCKET_ERROR==retval)
{
closesocket(m_socket);
cout<<"端口绑定失败! 错误ID为:"<<WSAGetLastError()<<endl;
return FALSE;
}
return TRUE;
}