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

来源:互联网 发布:淘宝手机详情怎么设置 编辑:程序博客网 时间:2024/05/26 02:19

环境;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;//服务端的socketWSADATA 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();}
0 0