您的位置:首页 > 理论基础 > 计算机网络

【tcp-ip学习总结】基于udp的多人聊天室,带有登录注册功能

2015-05-08 18:26 591 查看

环境;vs2010,vs2013

服务器端

#include<stdio.h>
#include<Winsock2.h>
#include<stdlib.h>
#pragma comment(lib,"Ws2_32.lib")

typedef struct {
char username[30];//用户名
char password[50];//用户密码
struct sockaddr_in addr;//用户的地址
int isOnlie;//是否在线
}User;

SOCKET severSocket;//服务端的socket
WSADATA wsaData;
struct sockaddr_in serverAddr, clientAddr, showMsgAddr;//服务器端地址,客户端地址,客户端那边消息显示框的地址
char recvBuf[1024];//接收缓冲区
struct sockaddr_in addrs[10];//客户端地址数组(装有每一个客户端的地址)
int count = 0;//地址数组中元素的个数
int clientaddrLen;//服务器端的地址长度
int recvlen;//接收字符串的长度
int i = 0;//循环需要的变量
int res;//字符串比较的结果
int sendLen;//发送数据的长度
char clientIP[1024];//保存当前客户端地址
char addrIP[1024];//保存数组中第i个客户端的地址
char command;//用户输入的命令
User users[100];
int userCount;//用户的数量
char sendBuf[1024];//发送给客户端的提示字符串
char username[30];//登陆人的名字
char password[50];//登陆人的密码
char *delimiters;//分割的字符串
int onlineCount;//显示在线人数
char onlineStr[100];//在线人数的字符串格式

/*登陆功能*/
void login(){
printf("登陆!\n");
//如果接收的整个字符串为a,就提示登陆方法,否则就执行登陆
if (!strcmp("a", recvBuf)) {
strcpy(sendBuf, "登陆请在发送框输入(a 用户名 密码)按回车\n");
sendLen = sendto(severSocket, sendBuf, sizeof(sendBuf), 0, (SOCKADDR*)&showMsgAddr, sizeof(showMsgAddr));
if (sendLen == SOCKET_ERROR) {
printf("发送失败!");
return;
}
}
else {
//分割字符串
delimiters = strtok(recvBuf, " ");
delimiters = strtok(NULL, " ");
strcpy(username, delimiters);//拿到登陆的username
delimiters = strtok(NULL, " ");
strcpy(password, delimiters);//拿到登陆的密码

for (i = 0; i < userCount; i++) {
if (!strcmp(username, users[i].username)){
if (!strcmp(password, users[i].password)) {
if (users[i].isOnlie == 1) {//判断是否重复登陆
strcpy(sendBuf, "不好意思您重复登陆了!\n");
sendLen = sendto(severSocket, sendBuf, sizeof(sendBuf), 0, (SOCKADDR*)&showMsgAddr, sizeof(showMsgAddr));
return;
}
else {
users[i].isOnlie = 1;
onlineCount++;
users[i].addr = showMsgAddr;
printf("一个客户登陆,客户的ip为:%s----端口号为%d\n", inet_ntoa(showMsgAddr.sin_addr), ntohs(showMsgAddr.sin_port));
sprintf(onlineStr, "%d", onlineCount);//吧int类型的数转为字符串
strcpy(sendBuf, "客户登陆,目前在线人数为 ");
strcat(sendBuf, onlineStr);
strcat(sendBuf, "\n");
//发送给所有的客户端
for (i = 0; i < userCount; i++) {
if (users[i].isOnlie == 1) {
sendLen = sendto(severSocket, sendBuf, sizeof(sendBuf), 0, (SOCKADDR*)&users[i].addr, sizeof(users[i].addr));
if (sendLen == SOCKET_ERROR) {
printf("发送失败!");
return;
}
}
}
return;
}
}
else {
strcpy(sendBuf, "密码错误\n");
sendLen = sendto(severSocket, sendBuf, sizeof(sendBuf), 0, (SOCKADDR*)&showMsgAddr, sizeof(showMsgAddr));
return;
}

}
}
strcpy(sendBuf, "不存在此用户名,请注册\n");
sendLen = sendto(severSocket, sendBuf, sizeof(sendBuf), 0, (SOCKADDR*)&showMsgAddr, sizeof(showMsgAddr));
return;
}
}

/*注册功能*/
void logout() {
printf("注册\n");
printf("一个客户正在注册,客户的ip为:%s----端口号为%d\n", inet_ntoa(showMsgAddr.sin_addr), ntohs(showMsgAddr.sin_port));
if (!strcmp("b", recvBuf)) {
strcpy(sendBuf, "注册请在发送框输入(b 用户名 密码)按回车\n");
sendLen = sendto(severSocket, sendBuf, sizeof(sendBuf), 0, (SOCKADDR*)&showMsgAddr, sizeof(showMsgAddr));
if (sendLen == SOCKET_ERROR) {
printf("发送失败!");
return;
}
}
else {
//分割字符串
delimiters = strtok(recvBuf, " ");
delimiters = strtok(NULL, " ");
strcpy(username, delimiters);//拿到注册的username
delimiters = strtok(NULL, " ");
strcpy(password, delimiters);//拿到注册的密码

/*判断是不是已经存在用户名*/
for (i = 0; i < userCount; i++) {
if(!strcmp(username, users[i].username) ){
strcpy(sendBuf, "用户名已经存在!\n");
sendLen = sendto(severSocket, sendBuf, sizeof(sendBuf), 0, (SOCKADDR*)&showMsgAddr, sizeof(showMsgAddr));
if (sendLen == SOCKET_ERROR) {
printf("发送失败!");
return;
}
}
}
//如果没有存在就给结构体赋值
strcpy(users[i].username, username);
strcpy(users[i].password, password);
users[i].addr = showMsgAddr;
userCount++;

strcpy(sendBuf, "注册成功,请登陆\n");
sendLen = sendto(severSocket, sendBuf, sizeof(sendBuf), 0, (SOCKADDR*)&showMsgAddr, sizeof(showMsgAddr));
if (sendLen == SOCKET_ERROR) {
printf("发送失败!");
return;
}
}
}

/*注销登陆*/
void  LogOff() {
/*判断发出注销功能的是哪一个用户*/
strcpy_s(clientIP, 1024, inet_ntoa(showMsgAddr.sin_addr));
for (i = 0; i < userCount; i++) {
strcpy_s(addrIP, 1024, inet_ntoa(users[i].addr.sin_addr));
if (!strcmp(clientIP, addrIP)) {
users[i].isOnlie = 0;
strcpy(sendBuf, "成功退出! ");
sendLen = sendto(severSocket, sendBuf, sizeof(sendBuf), 0, (SOCKADDR*)&showMsgAddr, sizeof(showMsgAddr));

}
}
onlineCount--;//在线人数-1
sprintf(onlineStr, "%d", onlineCount);
strcpy(sendBuf, "有一个用户退出,目前在线人数为 ");
strcat(sendBuf, onlineStr);
strcat(sendBuf, "\n");
for (i = 0; i < userCount; i++) {
if (users[i].isOnlie == 1) {
sendLen = sendto(severSocket, sendBuf, sizeof(sendBuf), 0, (SOCKADDR*)&users[i].addr, sizeof(users[i].addr));
if (sendLen == SOCKET_ERROR) {
printf("发送失败!");
return;
}
}
}
}

/*群聊功能*/
void groupChar() {
//printf("群聊\n");
if (!strcmp("c", recvBuf)) {
strcpy(sendBuf, "请畅所欲言吧!\n");
sendLen = sendto(severSocket, sendBuf, sizeof(sendBuf), 0, (SOCKADDR*)&showMsgAddr, sizeof(showMsgAddr));
if (sendLen == SOCKET_ERROR) {
printf("发送失败!");
return;
}
}
else {
strcpy_s(clientIP, 1024, inet_ntoa(showMsgAddr.sin_addr));
for (i = 0; i < userCount; i++) {
strcpy_s(addrIP, 1024, inet_ntoa(users[i].addr.sin_addr));
if (!strcmp(clientIP, addrIP)) {
strcpy(username, users[i].username);
}
}

strcat(username, " : ");
strcat(username, recvBuf);
strcpy(recvBuf, username);
//取出users里面的每一个用户
for (i = 0; i < userCount; i++) {
if (users[i].isOnlie == 1) {
sendLen = sendto(severSocket, recvBuf, sizeof(recvBuf), 0, (SOCKADDR*)&users[i].addr, sizeof(users[i].addr));
if (sendLen == SOCKET_ERROR) {
printf("发送失败!");
return;
}
}
}
}
}

/*私聊功能*/
void privateChat() {
printf("私聊\n");
}

void main() {

if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) {
printf("协议栈加载失败!");
return;
}

//创建socket
severSocket = socket(AF_INET, SOCK_DGRAM, 0);
if (severSocket == INVALID_SOCKET) {
printf("套接口创建失败!");
return;
}

//初始化地址
serverAddr.sin_family = AF_INET;
serverAddr.sin_port = htons(8888);
serverAddr.sin_addr.s_addr = htonl(INADDR_ANY);

//绑定套接口
if (bind(severSocket, (LPSOCKADDR)&serverAddr, sizeof(serverAddr)) == SOCKET_ERROR) {
printf("套接口绑定失败!");
return;
}

clientaddrLen = sizeof(clientAddr);
memset(recvBuf, 0, sizeof(recvBuf));

printf("-------------服务器在等待-------------\n");

//开始接收数据
while (1) {
recvlen = recvfrom(severSocket, recvBuf, 1024, 0, (SOCKADDR*)&clientAddr, &clientaddrLen);
showMsgAddr = clientAddr;
showMsgAddr.sin_port = ntohs(6666);//把端口地址改为6666

if (recvlen != 0) {
if (recvBuf[0] == 'a') {
login();
}
else if (recvBuf[0] == 'b') {
logout();
}
else if(!strcmp(recvBuf, "end")){
LogOff();
}
else {
groupChar();
}
}
}
closesocket(severSocket);
WSACleanup();

}


客户端

#include<stdio.h>
#include<Winsock2.h>
#include<stdlib.h>
#pragma comment(lib,"Ws2_32.lib")

SOCKET clientSocket;
WSADATA wsaData;
char sendBuf[1024];
struct sockaddr_in serverAddr;
int sendLen;//发送数据的长度

void main() {
//加载协议栈
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) {
printf("协议栈加载失败!");
return;
}

//创建客户端的socket
clientSocket = socket(AF_INET, SOCK_DGRAM, 0);
if (clientSocket == INVALID_SOCKET) {
printf("套接口创建失败!");
return;
}

//初始化目标服务器的地址
serverAddr.sin_family = AF_INET;
serverAddr.sin_port = htons(8888);
serverAddr.sin_addr.s_addr = inet_addr("172.18.130.230");

while (1) {
printf("输入要发送的数据:");
gets_s(sendBuf, 1024);
sendLen = sendto(clientSocket, sendBuf,sizeof(sendBuf),  0, (struct sockaddr*)&serverAddr, sizeof(serverAddr));
if (sendLen == SOCKET_ERROR) {
printf("发送失败!");
return;
}
}

}


客户端显示消息端

#include<stdio.h>
#include<Winsock2.h>
#include<stdlib.h>
#pragma comment(lib,"Ws2_32.lib")

SOCKET severSocket;
WSADATA wsaData;
struct sockaddr_in serverAddr, clientAddr;
char recvBuf[1024];
int recvlen;//接收数据的长度
int clientaddrLen;//客户端地址长度

void  showUI() {
printf("------------------------------------------------------------------\n");
printf("-----------------------欢迎来到狒狒聊天室-------------------------\n");
printf("------------------------请输入下列字母----------------------------\n");
printf("------------a:登陆    b:注册    c:群聊    d:私聊    end:退出登陆--------\n");
printf("------------------------------------------------------------------\n");
}

void main() {

if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) {
printf("协议栈加载失败!");
return;
}

//创建socket
severSocket = socket(AF_INET, SOCK_DGRAM, 0);
if (severSocket == INVALID_SOCKET) {
printf("套接口创建失败!");
return;
}

//初始化地址
serverAddr.sin_family = AF_INET;
serverAddr.sin_port = htons(6666);
serverAddr.sin_addr.s_addr = htonl(INADDR_ANY);

//绑定套接口
if (bind(severSocket, (LPSOCKADDR)&serverAddr, sizeof(serverAddr)) == SOCKET_ERROR) {
printf("套接口绑定失败!");
return;
}

clientaddrLen = sizeof(clientAddr);
memset(recvBuf, 0, sizeof(recvBuf));
showUI();//调用显示界面函数

//开始接收数据
while (1) {
recvlen = recvfrom(severSocket, recvBuf, 1024, 0, (SOCKADDR*)&clientAddr, &clientaddrLen);
if (recvlen != 0) {
printf("%s\n", recvBuf);
//printf("客户的ip为:%s----端口号为%d", inet_ntoa(clientAddr.sin_addr), ntohs(clientAddr.sin_port));

//发送给客户
//int sendLen = sendto(severSocket, recvBuf, sizeof(recvBuf), 0, (SOCKADDR*)&clientAddr, clientaddrLen);
//if (sendLen == SOCKET_ERROR) {
//  printf("发送失败!");
//  break;
//}
}
}
closesocket(severSocket);
WSACleanup();

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: