设计目标:
2.设计二 简单的即时通信软件(6学时实验)
目的与要求: 利用WinSock进行点对点通信,工作机制模仿即时通信软件的基本功能,登陆,上线,传递信息等等。分为客户部分和服务器部分两块,客户部分类似一般通信软件例如QQ,服务器部分主要提供客户端用户基本数据配置。
服务端代码:
#include <WinSock2.h>
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <string>
#include <sstream>
#pragma comment(lib,"pthreadVC2.lib")
#pragma comment(lib,"ws2_32.lib")
#include<iostream>
using namespace std;
/*void* recv1(SOCKET sockConn)
{ char recvBuf[10000];
memset(recvBuf, 0, sizeof(recvBuf));
//接收数据
while(true){
int nRecv = ::recv(sockConn, recvBuf, sizeof(recvBuf), 0);
cout<<endl;
if(nRecv>0)cout<<"他说:"<<recvBuf<<endl;
else break;}
}*/
SOCKET sockConn[10];
char password[] = "123456";
int pass = 0;
const int nl = 100;
string user[nl] = { "123","456","789","张三" };
string pw[nl] = { "111","456","789","张三" };
int online[nl] = {0,0,0};//判断是否在线的数组
int match[nl] = {-1,-1,-1};//表示第i个用户名匹配的是第几个套接字
int find(string a[], string b)
{
bool exist = false;
for (int j = 0; j<nl; j++)
{
if (a[j] == b)
{
exist = true;
return j;
}
}
if (!exist)
return -1;
}
int find1(SOCKET sock)
{
for (int i = 0; i < 10; i++)
{
if (sock == sockConn[i])
{
return i;
break;
}
}
return -1;
}
int finds(string s)//根据用户名找到对应的套接字
{
int index = find(user,s);
if (index >= 0)
return match[index];
else
return -1;
}
int findu(SOCKET sock )//根据套接字找用户名在数组中的位置
{
int index = find1(sock);
for (int i = 0; i < nl; i++)
{
if (match[i] == index)
return i;
}
return -1;
}
int nul_index(string a[])//查找string数组的空位,以便于用户注册的插入
{
for (int i = 0; i < nl; i++)
{
if (a[i].empty())
return i;
}
return nl;//没有空位,注册已满
}
void* recv1(void* args)
{
char recvBuf[10000];
char users[1000];
char pws[1000];
//接收数据
bool success = false;//判断是否登录成功
int id1 = (unsigned int)pthread_getw32threadid_np(pthread_self()) / 2;
SOCKET sockConn1 = *((SOCKET*)args);//建立套接字
memset(recvBuf, 0, sizeof(recvBuf));
int rel = 0;
rel = recv(sockConn1, recvBuf, sizeof(recvBuf), 0);
if (rel<0)
cout << "接受失败\n";
cout << rel<<" "<<recvBuf<<endl;
send(sockConn1, "ack", sizeof(recvBuf),0);
//cout<<recvBuf<<endl;
if (strcmp(recvBuf, "1") == 0)//客户端选择登录
{
cout << "选择登录服务\n";
memset(users, 0, sizeof(users));
rel = recv(sockConn1, users, sizeof(users), 0);
if (rel<0)//接受用户名
cout << "recv failed";
cout <<rel<<" "<< users << endl;
send(sockConn1, "ack", sizeof(recvBuf),0);
int index = find(user, users);//判断能否找到用户名
int sockNum = find1(sockConn1);
if (index != -1)//找到用户名
{
if (online[index] == 0)
{
cout << "找到用户名" << endl;
memset(pws, 0, sizeof(pws));
if (recv(sockConn1, pws, sizeof(pws), 0) < 0)//接受密码
cout << "recv failed";
cout << pws << endl;
if (pws == pw[index])//密码正确
{
online[index] = 1;
success = true;
match[index] = sockNum;
if (send(sockConn1, "密码正确", sizeof(recvBuf), 0) < 0)
{
cout << "发送失败";
}
}
else//密码错误
{
send(sockConn1, "密码错误", sizeof(recvBuf), 0);
}
}
else
{
memset(pws, 0, sizeof(pws));
if (recv(sockConn1, pws, sizeof(pws), 0)<0)//接受密码
cout << "recv failed";
if (send(sockConn1, "该用户已存在", sizeof(recvBuf), 0)<0)
cout << "发送失败";
}
}
if (index == -1)//未找到用户名
{
memset(pws, 0, sizeof(pws));
if (recv(sockConn1, pws, sizeof(pws), 0)<0)//接受密码
cout << "recv failed";
if (send(sockConn1, "用户名不存在", sizeof(recvBuf), 0)<0)
cout << "发送失败";
}
if (success)
{
char buf[1000];
int id = find1(sockConn1);
int n = findu(sockConn1);
const char*p=user[n].data();
//user[n].copy(p, 40, 0);//这里5,代表复制几个字符,0代表复制的位置
//*(p + 40) = '\0';//要手动加上结束符
if (id >= 1)
{
for (int j = 1; j < id + 1; j++)//好友上线功能
{
if (send(sockConn[j - 1], p, sizeof(p), 0) < 0) //,sizeof(buf),0)<0)
cout << "send failed";
if (send(sockConn[j - 1], "已上线", sizeof(buf), 0) < 0)
cout << "send failed";
}
}
while (true)
{
memset(recvBuf, 0, sizeof(recvBuf));
recv(sockConn1,recvBuf,sizeof(recvBuf),0);//接受要发送的用户名
int index = find(user,recvBuf);//查找要发送用户名的位置
if(strcmp(recvBuf, "all") == 0)//实现群发
{
memset(recvBuf, 0, sizeof(recvBuf));
recv(sockConn1, recvBuf, sizeof(recvBuf), 0);
for (int i = 0; i < nl; i++)
{
if (online[i] == 1&&i!=findu(sockConn1))
{
string a = user[n] + ": ";
const char* pp = a.data();
sockNum = finds(user[i]);
if (send(sockConn[sockNum], pp, sizeof(pp), 0) < 0) //,sizeof(buf),0)<0)
cout << "send failed";
send(sockConn[sockNum], recvBuf, sizeof(recvBuf), 0);
}
}
}
else
{
if (strcmp(recvBuf, "退出") == 0)//用户选择退出
{
int i