MyMsg.h
- #pragma once
- /************************************************************
- * 文件名:MyMsg.h
- * 描述: 服务器和客户端共用的头文件,消息定义
- *************************************************************/
- #ifndef _MYMSG_H_
- #define _MYMSG_H_
- enum {
- LOGIN_MSG, //登录
- LOGIN_MSG_RES, //登录响应
- QUERY_FQQ, //查询单个好友QQ
- QUERY_FQQ_RES, //查询单个好友QQ的响应
- TALK_MSG, //聊天
- REQUEST_ALL_FRD, //请求所有qq好友信息
- APPLY_ALL_FRD //应答所有qq好友信息
- };
- struct LoginMsg {
- unsigned char id; //消息编号
- char qq[6]; //登录ID号
- };
- struct LoginMsgResponse {
- unsigned char id; //消息编号
- unsigned char isOK;
- char reason[100]; //如果失败,则在此写入失败原因
- };
- struct FriendQqMsg {
- unsigned char id; //消息编号
- char qq[6];
- };
- struct FriendQqMsgResponse {
- unsigned char id; //消息编号
- unsigned char isOK;
- };
- struct TalkMsg {
- unsigned char id; //消息编号
- char qq[6];
- char fqq[6];
- char info[200];
- };
- struct RequestAllFriend {
- unsigned char id; //消息编号
- };
- struct AllFriendMsg {
- unsigned char id; //消息编号
- char qq[6];
- };
- #endif
MyTcp.cpp
- /************************************************************
- * 文件名:MyTCP.cpp
- * 描述: TCP/IP通信socket封装
- *************************************************************/
- #include <stdio.h>
- #include <WinSock2.h>
- #include "MyTools.h"
- #pragma comment (lib, "ws2_32.lib")
- #define PORT 5001
- int ls; //侦听套接字
- int flag;//记录服务器或是客户端的标志
- /* 描述: 初始化服务器或客户端, 该函数在使用中必需首先调用,客户端和服务器 */
- int initSock(int IsServer)
- {
- WSADATA data;
- if (WSAStartup(1, &data) <0)
- printMsgExit("call WSAStartup() failure!");
- ls = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
- if (ls < 0)
- printMsgExit("创建套接字失败!");
- flag = IsServer;
- if (IsServer != 0)
- {//服务器
- struct sockaddr_in servAddr;
- memset(&servAddr, 0, sizeof(servAddr));
- servAddr.sin_family = AF_INET;
- servAddr.sin_addr.s_addr = htonl(INADDR_ANY);
- servAddr.sin_port = htons(PORT);
- if (bind(ls, (struct sockaddr *)&servAddr, sizeof(servAddr))<0) {
- printMsg("bind套接字失败!\n");
- return -1;
- }
- if (listen(ls, 10)<0) {
- printMsg("listen套接字失败!\n");
- return -1;
- }
- }
- return 0;
- }
- /* 描述: 仅用于客户端, 连接服务器 */
- int tcpConnect(const char *serverIP, unsigned short port)
- {
- struct sockaddr_in servAddr;
- memset(&servAddr, 0, sizeof(servAddr));
- servAddr.sin_family = AF_INET;
- servAddr.sin_addr.s_addr = inet_addr(serverIP);
- servAddr.sin_port = htons(port);
- if (connect(ls, (struct sockaddr *)&servAddr, sizeof(servAddr))<0)
- {
- printMsgExit("连接服务器失败!\n");
- }
- return ls;
- }
- /* 描述: 发送数据 */
- int tcpSend(unsigned int sock, const char *sendBuf, int sendBufLen)
- {
- int len = send(sock, sendBuf, sendBufLen, 0);
- return len;
- }
- /* 描述: 接收数据 */
- int tcpRecv(unsigned int sock, char *recvBuf, int recvBufLen)
- {
- int len = recv(sock, recvBuf, recvBufLen, 0);
- return len;
- }
- void tcpClose(unsigned int sock)
- {
- closesocket(sock);
- WSACleanup();
- }
MyTcp.h
- #pragma once
- /************************************************************
- * 文件名:MyTCP.h
- * 描述: TCP通信头文件
- *************************************************************/
- #ifndef _MYTCP_H_
- #define _MYTCP_H_
- int initSock(int IsServer);
- int tcpConnect(const char *serverIP, unsigned short port);
- int tcpAccept();
- int tcpSend(unsigned int sock, const char *sendBuf, int sendBufLen);
- int tcpRecv(unsigned int sock, char *recvBuf, int recvBufLen);
- void tcpClose(unsigned int sock);
- #endif
MyTools.cpp
- /************************************************************
- * 文件名:MyTools.cpp
- * 描述: 共用的文件,工具函数定义
- *************************************************************/
- #include <stdio.h>
- #include <stdlib.h>
- #include "MyTools.h"
- extern int flag;
- void printMsg(const char * msg) {
- if (flag)
- printf("\t【南工服务器豪华版】%s", msg);
- else
- printf("\t【南工客户端豪华版】%s", msg);
- }
- void printInt(int value) {
- if (flag)
- printf("\t【南工服务器豪华版】%d", value);
- else
- printf("\t【南工客户端豪华版】%d", value);
- }
- void printMsgExit(const char * msg) {
- printMsg(msg);
- exit(0);
- }
- void printIntExit(int value) {
- printInt(value);
- exit(0);
- }
- #pragma once
- /************************************************************
- * 文件名:MyTools.h
- * 描述:工具函数定义
- *************************************************************/
- #ifndef _MYTOOLS_H_
- #define _MYTOOLS_H_
- void printMsgExit(const char * msg);
- void printMsg(const char * msg);
- void printInt(int value);
- void printIntExit(int value);
- #endif
TalkClient.cpp
- /************************************************************
- * 文件名:TalkClient.cpp
- * 描述: 客户端入口,界面操作
- *************************************************************/
- #include <stdio.h>
- #include <Windows.h>
- #include "TalkClientService.h"
- void displayMenu();
- void exitProc();
- void defProc();
- void procMenu();
- char serverip[6];
- int main(int argc, char *argv[])
- {
- if (argc < 2)
- {
- printf("请输入服务器的IP地址。。。\n");
- return 0;
- }
- strcpy(serverip, argv[1]);
- displayMenu();
- procMenu();
- while (1) Sleep(10000);
- }
- char ch; //菜单选择
- void displayMenu()
- {
- static int t = 1;
- if (t++ == 1)
- {
- printf("\n\n\n\n\n");
- printf("\n\t @ @ ");
- printf("\n\t @ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @ ");
- printf("\n\t @ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @ ");
- printf("\n\t @ ** ** ********** ** ** ******** ** ** @ ");
- printf("\n\t @ ** ** ** ** ** ** ** ** ** @ ");
- printf("\n\t @ ** ** ** ** ** ** ** ** ** @ ");
- printf("\n\t @ ********** ********** ** ** ** ** ** ** @ ");
- printf("\n\t @ ** ** ** ** ** ** ** ** ** @ ");
- printf("\n\t @ ** ** ** ** ** ** ** @ ");
- printf("\n\t @ ** ** ********** ******** ******** ******** @@ @@ @ ");
- printf("\n\t @ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @ ");
- printf("\n\t @ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^@ ");
- printf("\n\t @ @ ");
- printf("\n -----By Hins ");
- printf("\n\n\n\n\n\t\tPress 'Enter' to enter the menu......"); /*按任一键进入主菜单*/
- }
- getchar(); /*从键盘读取一个字符,但不显示于屏幕*/
- system("cls"); /*清屏*/
- printf("\n");
- printf("\n");
- printf("\n");
- printf("\t************************************************\n");
- printf("\t* *\n");
- printf("\t* 南工2016聊天客户端程序 *\n");
- printf("\t* Version 2.1 豪华版 *\n");
- printf("\t* *\n");
- printf("\t* *\n");
- printf("\t* *\n");
- printf("\t* 1) 登录(L) *\n");
- printf("\t* 2) 退出(e) *\n");
- printf("\t* by---HinsShwan *\n");
- printf("\t************************************************\n");
- printf("\n");
- connectServer();
- printf("\t您的选择是:");
- ch = getchar();
- }
- void procMenu()
- {
- switch (ch)
- {
- case 'l':
- case 'L':
- case '1':
- statusConnected();
- break;
- case 'e':
- case 'E':
- case '2':
- exitProc();
- break;
- default:
- defProc();
- }
- }
- void exitProc()
- {
- printf("\t客户端程序已经终止!\n");
- exit(0);
- }
- void defProc()
- {
- printf("\t 输入字符错误!\n");
- }
TalkClientService.cpp
- /************************************************************
- * 文件名:TalkClientService.cpp
- * 描述: 客户端业务实现
- *************************************************************/
- #include "MyTCP.h"
- #include "MyTools.h"
- #include "TalkClientService.h"
- void myRecvThread();
- #define PORT 5001
- extern char serverip[6];
- char qq[6] = { 0 };
- char fqq[6] = { 0 };
- int sock;
- int status = STUS_START;
- void mainProc()
- {
- while (1)
- {
- switch (status)
- {
- case STUS_CONNECTED:
- statusConnected();
- break;
- case STUS_WAIT_LOGIN_RES:
- printMsg("等待服务器响应..........\n");
- Sleep(1000);
- break;
- case STUS_LOGINED:
- statusLogined();
- break;
- case STUS_WAIT_QUERY_FQQ_RES:
- printMsg("等待服务器响应..........\n");
- Sleep(1000);
- break;
- case STUS_TALK:
- statusTalk();
- break;
- case STUS_WAIT_QUERY_ALLQQ_RES:
- printMsg("等待服务器响应..........\n");
- Sleep(1000);
- break;
- }
- }
- }
- void statusTalk()
- {
- printMsg("退出聊天(Exit) 我说>>");
- setbuf(stdin, NULL); //清空键盘缓冲区
- char buf[1024] = { 0 };
- gets_s(buf);
- if (strcmp(buf, "Exit") == 0)
- {
- printMsg("客户端已经退出!\n");
- statusLogined();
- }
- else
- {
- struct TalkMsg msg;
- msg.id = TALK_MSG;
- strcpy(msg.qq, qq);
- strcpy(msg.fqq, fqq);
- strcpy(msg.info, buf);
- status = 5;
- tcpSend(sock, (const char *)&msg, sizeof(msg));
- }
- return;
- }
- void statusLogined()
- {
- char buf0[10] = { 0 };
- int rt = 0;
- while (rt == 0)
- {
- memset(buf0, 0, sizeof(buf0));
- printMsg("显示在线好友(L)|找好友聊天(T)|退出(E) 默认(T)>>");
- setbuf(stdin, NULL); //清空键盘缓冲区
- gets_s(buf0);
- if (strcmp(buf0, "T") == 0 || strcmp(buf0, "t") == 0)
- {
- printMsg("选择聊天好友......\n");
- while (1)
- {
- printMsg("输入聊天好友QQ号(最多不超过5位): 退出请输入“quit”");
- char tmp[1024];
- scanf("%s", tmp);
- if (strlen(tmp) > 5)
- {
- printMsg("您输入的qq号长度大于5个,请重新输入\n");
- }
- else if (strcmp(tmp, qq) == 0)
- {
- printMsg("您输入的qq号是自己号码,难道您要自言自语吗?::) 请重新输入\n");
- }
- else if (strcmp(tmp, "quit") == 0)
- break;
- else
- { //发送要聊天的好友QQ号给服务器
- struct FriendQqMsg msg;
- msg.id = QUERY_FQQ;
- strcpy(msg.qq, tmp);
- strcpy(fqq, tmp);
- status = STUS_WAIT_QUERY_FQQ_RES;
- tcpSend(sock, (const char *)&msg, sizeof(msg));
- rt = 1;
- break;
- }
- }
- }
- else if (strcmp(buf0, "L") == 0 || strcmp(buf0, "l") == 0)
- {
- char buf2[10] = { 0 };
- memset(buf2, 0, sizeof(buf2));
- struct RequestAllFriend res;
- res.id = REQUEST_ALL_FRD;
- memcpy(buf2, &res, sizeof(res));
- tcpSend(sock, (const char*)buf2, sizeof(buf2));
- status = STUS_WAIT_QUERY_ALLQQ_RES;
- Sleep(100);
- }
- else if (strcmp(buf0, "E") == 0 || strcmp(buf0, "e") == 0)
- {
- printMsg("客户端已经退出!\n");
- exit(0);
- }
- else
- {
- printMsg("输入内容错误(手抖了吧-_-),请重新输入\n");
- }
- };
- }
- void connectServer()
- {
- printMsg("开始连接服务器......\n");
- initSock(0); //客户端
- sock = tcpConnect(serverip, PORT);
- printMsg("连接服务器成功!\n");
- //创建一个线程用于接收服务器发送的信息
- DWORD threadId;
- CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)myRecvThread, NULL, 0, &threadId);
- }
- //创建接收线程专用于接收并处理服务器返回的收数据
- void myRecvThread()
- {
- char buf[1024] = { 0 };
- while (1)
- {
- memset(buf, 0, sizeof(buf));
- tcpRecv(sock, buf, sizeof(buf));
- unsigned char id = (unsigned char)buf[0];
- switch (id)
- {
- case LOGIN_MSG_RES:
- procLoginMsgResponse((struct LoginMsgResponse *)buf);
- break;
- case QUERY_FQQ_RES:
- procFriendQqMsgResponse((struct FriendQqMsgResponse *)buf);
- break;
- case TALK_MSG:
- procTalkMsg((struct TalkMsg *)buf);
- break;
- case APPLY_ALL_FRD:
- procApplyAllFriend((struct AllFriendMsg *)buf);
- break;
- }
- }
- sprintf(buf, "结束myRecvThread线程:%d.........\n");
- printMsg(buf);
- exit(0);
- }
- void statusConnected()
- {
- printMsg("\n\t请输入登录信息\n");
- while (1)
- {
- printMsg("本机的QQ号(最多不超过5位数字):");
- char tmp[1024];
- scanf("%s", tmp);
- int i;
- if (strlen(tmp)>5)
- {
- printMsg("您输入的qq号长度大于5个,请重新输入\n");
- continue;
- }
- for (i = 0;i<strlen(tmp);i++)
- {
- if (tmp[i] >= '0' && tmp[i] <= '9')
- {
- continue;
- }
- else
- break;
- }
- if (i == strlen(tmp))
- {
- strcpy(qq, tmp);
- break;
- }
- else
- {
- printMsg("输入信息有误,请重新输入\n");
- continue;
- }
- }
- struct LoginMsg msg;
- msg.id = LOGIN_MSG;
- status = STUS_WAIT_LOGIN_RES;
- strcpy(msg.qq, qq);
- tcpSend(sock, (const char *)&msg, sizeof(msg));
- mainProc(); //进入主处理程序
- return;
- }
- void procLoginMsgResponse(struct LoginMsgResponse *msg)
- {
- if (msg->isOK == 1)
- {
- printMsg("登录成功!\n");
- status = STUS_LOGINED;//已登录状态
- }
- else
- {
- printMsg("登录失败!\n");
- printMsgExit(msg->reason);
- printf("\n");
- }
- }
- void procFriendQqMsgResponse(struct FriendQqMsgResponse *msg)
- {
- if (msg->isOK == 1)
- {
- printMsg("好友目前在线,可以开始聊天...\n");
- status = STUS_TALK;
- }
- else
- {
- printMsg("好友不存在啊,再换个人试试!\n");
- status = STUS_LOGINED;
- }
- }
- void procTalkMsg(struct TalkMsg *msg)
- {
- char buf[1024] = { 0 };
- if (strcmp(msg->qq, fqq) == 0)
- {//表示是自己发起的聊天,仅仅显示信息即可
- printf("\n");
- sprintf(buf, "%s说>>%s", fqq, msg->info);
- printMsg(buf);
- }
- else
- {//是陌生人发起的聊天
- printf("\n");
- sprintf(buf, "%s说>>%s", msg->qq, msg->info);
- printMsg(buf);
- }
- }
- void procApplyAllFriend(struct AllFriendMsg *msg)
- {<pre name="code" class="html">#pragma once
- /************************************************************
- * 文件名:TalkClientService.h
- * 描述: 客户端业务层函数声明
- *************************************************************/
- #ifndef _TALKCLIENTSERVICE_H_
- #define _TALKCLIENTSERVICE_H_
- #include <Windows.h>
- #include <stdio.h>
- #include <string.h>
- #include <stdlib.h>
- #include "MyMsg.h"
- void connectServer();
- void procLoginMsgResponse(struct LoginMsgResponse *msg);
- void procFriendQqMsgResponse(struct FriendQqMsgResponse *msg);
- void procTalkMsg(struct TalkMsg *msg);
- void statusConnected();
- void statusLogined();
- void statusTalk();
- void procApplyAllFriend(struct AllFriendMsg *msg);
- /** 客户端状态 **/
- enum {
- STUS_START,
- STUS_CONNECTED,
- STUS_WAIT_LOGIN_RES,
- STUS_LOGINED,
- STUS_WAIT_QUERY_FQQ_RES,
- STUS_TALK,
- STUS_WAIT_QUERY_ALLQQ_RES
- };
- #endif
char buf[100] = { 0 };sprintf(buf, "%s", msg->qq);printMsg("在线的QQ好友: \n");printMsg(buf);printf("\n");status = STUS_LOGINED;}
TalkClientService.h