基于TCP协议的聊天室详细教学(C++)

这篇具有很好参考价值的文章主要介绍了基于TCP协议的聊天室详细教学(C++)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一、设计工具

1.ide: VS2010旗舰版(学生版应该也可以)

2.编程语言: C++

二、效果展示

1.服务器效果

服务器只转发消息不参到信息交流中

基于TCP协议的聊天室详细教学(C++)

 2.客户端效果

客户端输入用户名后默认进入群聊模式,输入“获取用户列表”可以获取在线用户用户名列表,如果需要私聊某一个用户需要输入“私聊+用户名”可进入私聊模式,输入“退出私聊”可退出私聊重新进入群聊模式。

基于TCP协议的聊天室详细教学(C++)

基本群聊展示

基于TCP协议的聊天室详细教学(C++)

获取用户列表展示

基于TCP协议的聊天室详细教学(C++)

私聊效果展示

基于TCP协议的聊天室详细教学(C++)

 三、代码讲解

1.C++使用TCP协议基本结构

ps:我们在使用tcp协议是不需要完全了解这部分代码的作用,只需要了解怎么初始化和使用它就行

1.确定协议版本信息

基于TCP协议的聊天室详细教学(C++)

2.创建socket

基于TCP协议的聊天室详细教学(C++)

3.确定服务器地址族

基于TCP协议的聊天室详细教学(C++)

4.连接服务器

基于TCP协议的聊天室详细教学(C++)

5.使用后关闭scoket和清理协议版本信息,减少系统占用

基于TCP协议的聊天室详细教学(C++)

2.客户端程序

(1)连接到客户端时使用用户名设定模块,将输入的用户名发送到服务器存储

基于TCP协议的聊天室详细教学(C++)

(2)通信函数,用于在多线程函数中使用

基于TCP协议的聊天室详细教学(C++)

(3)收发消息实现模块,如果收到消息,使用标准输出\b和输出空格遮挡通信函数输出的基础内容,再重新打印一次使得控制台程序收发消息美观

基于TCP协议的聊天室详细教学(C++)

(4)客户端整体代码如下 

#include<stdio.h>
#include<WinSock.h>
#include<Windows.h>
#pragma comment(lib,"ws2_32.lib")
//创建socket数组
SOCKET serverSocket;
//全局变量
char name[256] = "设定用户名";
//函数声明
static int getNumber(const char *s);//中英文混合用户名长度检测函数
void findIP(char *ip, int size);//读取本机一个ip

void yonghu() {
	//5通信
	char buff[256];
	while(1) {
		printf("%s:>",name);
		scanf("%s",buff);
		send(serverSocket,buff,strlen(buff),NULL);
	}
}

int main() {
	printf("\n**********************欢迎使用 210745班 小马的 tcp聊天室*************************");
	printf("\n**************默认为群聊模式,输入“获取用户列表”可获取在线用户列表*************");
	printf("\n*****输入“私聊+对方用户名”可进入私聊模式,输入“退出私聊”可以恢复群聊模式*****\n");
	char ip[20] = {0};
	findIP(ip, sizeof(ip));//读取本机ip
	//initgraph(300,300,1);  //图形库函数
	//1 确定协议版本信息
	WSADATA wsaData;
	WSAStartup(MAKEWORD(2,2),&wsaData);
	if (LOBYTE(wsaData.wVersion) != 2  ||  HIBYTE(wsaData.wVersion) != 2) {
		printf("确定版本协议信息错误:%d",GetLastError());
		return -1;
	}
	printf("确定版本协议信息成功\n");
	//2 创建socket
	serverSocket = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
	if( SOCKET_ERROR == serverSocket) {
		WSACleanup();
		printf("创建socket错误:%d",GetLastError());
		return -1;
	}
	printf("创建socket成功\n");

	//3 确定服务器协议地址族
	SOCKADDR_IN  sAddr = { 0 };
	sAddr.sin_family = AF_INET;
	sAddr.sin_addr.S_un.S_addr = inet_addr(ip);
	sAddr.sin_port = htons(9527);//一般的pc机 65536
	
	//4 连接服务器
	int r = connect(serverSocket,(sockaddr*)&sAddr,sizeof sAddr);
	if(-1 == r) {
		closesocket(serverSocket);
		WSACleanup();
		printf("连接服务器错误:%d\n",GetLastError());
	}
	printf("连接服务器成功\n");

	//用户名设定模块
	char buff[256];
	sprintf(buff,"%s",name);
	send(serverSocket,buff,strlen(buff),NULL);

	memset(name,0,sizeof(name));
	printf("\n请输入用户名:");
	scanf("%s",name);
	sprintf(buff,"%s",name);
	send(serverSocket,buff,strlen(buff),NULL);

	//同时要接受服务器发来的数据并现实
	CreateThread(NULL,NULL,
		(LPTHREAD_START_ROUTINE)yonghu,
		NULL,NULL,NULL);
	//接受服务器发来的消息并显示
	char recvBuff[256];
	int n = 0;
	while(1) {
		r = recv(serverSocket, recvBuff, 255, NULL);
		recvBuff[r] = 0;

		if(r>0) {
			for(r=0; r<=getNumber(name)+2; r++) { printf("\b"); }
			for(r=0; r<=getNumber(name)+2; r++) { printf(" "); }
			for(r=0; r<=getNumber(name)+2; r++) { printf("\b"); }
			printf("%s\n",recvBuff);
			printf("%s:>",name);
		}
		out:;
	}


	//6关闭socket
	closesocket(serverSocket);
	//7清理协议版本信息
	WSACleanup();


	return 0;
}

static int getNumber(const char *s)
{
    int i = 0, j = 0;
    while (s[i])
    {
    	
        if ((s[i] & 0xc0) != 0x80) j++;
        i++;
    }
    return j;
}

void findIP(char *ip, int size) 
{
	WORD v = MAKEWORD(1, 1);
	WSADATA wsaData;
	WSAStartup(v, &wsaData); // 加载套接字库
 
	struct hostent *phostinfo = gethostbyname("");
	char *p = inet_ntoa (* ((struct in_addr *)(*phostinfo->h_addr_list)) ); 				
	strncpy(ip, p, size - 1);
	ip[size - 1] = '\0';
	WSACleanup( );
} 

3.服务器程序

(1)除accept函数处理部分tcp协议初始化步骤与客户端相同,这里不再赘述

(2)将accept函数放在一个for循环中接受多个客户端连接,NUM是一个宏定义的参数,可以设置最大用户接入数量

基于TCP协议的聊天室详细教学(C++)

(3)设定用户名模块。使用字符串处理函数strcmp识别特殊字符,存储客户端用户名到一个指针数组,strcat可以将用户名拼接到用户列表中

基于TCP协议的聊天室详细教学(C++)

(4)私聊模块。服务器通过识别特殊字符开启私聊模式,因为我设计程序时用户名指针数组跟socket的下标是对应的,利用这个特性可以用循环识别客户端需要私聊的用户,发送给对于socket[]数组中的一个就实现了私聊,输入退出私聊时服务器也可以识别,使用goto out:跳出这个模块。

基于TCP协议的聊天室详细教学(C++)

(5)群聊模块。在群聊模式下,使用for循环将收到的客户端消息广播到所有客户端

基于TCP协议的聊天室详细教学(C++)

(6)服务器端整体代码如下 

#include<stdio.h>
#include<WinSock.h>
#include<Windows.h>
#pragma comment(lib,"ws2_32.lib")
//宏定义
#define NUM 1024
//函数声明
static int getNumber(const char *s);//中英文混合用户名长度检测函数
void findIP(char *ip, int size);//读取本机一个ip
//全局变量
char *name[1023];//1024个用户名
int clientCount;
char namelist[512] = "*******用户列表*******\n";
//创建socket数组
SOCKET clientSocket[NUM];//设置最多1024客户端接入

void tongxin(int idx) {
	//7 通信
	char buff[256];
	char mid[256];
	int r;
	int i;
	char temp[256];
	char siliao[256];
	char num[256];

	while(1) {

		r = recv(clientSocket[idx],buff,255,NULL);
		if (r>0) {
		buff[r] = 0;//添加结束符号
		
		if(strcmp(buff,"设定用户名") == 0) {//用户名设定模块
		memset(buff,0,256);
		recv(clientSocket[idx],buff,255,NULL);
		strcpy(mid,buff);
		name[idx] = mid;
		sprintf(name[idx],"%s",buff);
		//更新用户列表
		sprintf(temp,"%s",buff);
		strcat(namelist,"");
		strcat(namelist,name[idx]);
		strcat(namelist,"\n");
		goto out;
		}

		if(strcmp(buff,"获取用户列表") == 0) {
		memset(temp,0,256);
		strcpy(temp,namelist);
		send(clientSocket[idx],temp,strlen(temp),NULL);
		goto out4;
		}

		for(i=0;i<=1023;i++) {
			sprintf(siliao,"私聊%s",name[i]);
			if(strcmp(buff,siliao) == 0) {
				memset(temp,0,256);//清空数组
				sprintf(temp,"服务器已准备好向%s发送私聊消息\n输入“退出私聊”可以继续群聊\n",name[i]);
				send(clientSocket[idx],temp,strlen(temp),NULL);
				memset(temp,0,256);//清空数组
				sprintf(temp,"%s将对您发送私聊消息\n",name[idx]);
				send(clientSocket[i],temp,strlen(temp),NULL);
				while(1) {
					memset(buff,0,256);//清空数组
					recv(clientSocket[idx],buff,255,NULL);
					printf("%s:>%s\n",name[i],buff);
					if(strcmp(buff,"退出私聊") == 0) {
						memset(temp,0,256);
						sprintf(temp,"已退出私聊模式,即将进入群聊\n",name);
						send(clientSocket[idx],temp,strlen(temp),NULL);
						goto out2;
					}
					memset(temp,0,256);//清空数组
					sprintf(temp,"%s:>%s",name[idx],buff);
					send(clientSocket[i],temp,strlen(temp),NULL);
				}
			}
		}

		//printf(">>:%s\n",buff);
		memset(temp,0,256);//清空数组
		sprintf(temp,"%s:>%s",name[idx],buff);
		for(int i = 0;i < clientCount;i++) {//广播
			if( i == idx ) continue; //不广播给自己
			send(clientSocket[i],temp,strlen(temp),NULL);
		}

		}
	out:; out2:; out3:;out4:;
	}
}

int main() {
	clientCount = 0;
	char ip[20] = {0};
	findIP(ip, sizeof(ip));//读取本机ip
	//1 确定协议版本信息
	WSADATA wsaData;
	WSAStartup(MAKEWORD(2,2),&wsaData);
	if (LOBYTE(wsaData.wVersion) != 2  ||  HIBYTE(wsaData.wVersion) != 2) {
		printf("确定版本协议信息错误:%d",GetLastError());
		return -1;
	}
	printf("确定版本协议信息成功\n");
	//2 创建socket
	SOCKET serverSocket = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
	if( SOCKET_ERROR == serverSocket) {
	//9清理协议版本信息
	WSACleanup();
	printf("创建socket错误:%d",GetLastError());
	return -1;
	}
	printf("创建socket成功\n");

	//3 确定服务器协议地址族
	SOCKADDR_IN  sAddr = { 0 };
	sAddr.sin_family = AF_INET;
	sAddr.sin_addr.S_un.S_addr = inet_addr(ip);
	sAddr.sin_port = htons(9527);//一般的pc机 65536
	//4 绑定
	int r = bind(serverSocket,(sockaddr*)&sAddr,sizeof(sAddr));
	if(-1 == r) {
		 //8关闭socket
		closesocket(serverSocket);
		 //9清理协议版本信息
		WSACleanup();
		printf("绑定错误:%d\n",GetLastError());
	}
	printf("绑定成功\n");
	//5 监听
	r = listen(serverSocket,10);
	if(-1 == r) {
		//8关闭socket
		closesocket(serverSocket);
		//9清理协议版本信息
		WSACleanup();
		printf("监听错误:%d\n",GetLastError());
	}
	printf("监听成功\n");
	//6 接受连接
	for(int i = 0; i<NUM; i++) {
		clientSocket[i] = accept(serverSocket,NULL,NULL);
	if( SOCKET_ERROR == clientSocket[i]) {
		 //8关闭socket
		closesocket(serverSocket);
		 //9清理协议版本信息
		WSACleanup();
		printf("网络崩了%d\n",GetLastError());
		return -1;
	}

	printf("客户端连接上服务器了!\n");
	clientCount++;

	//7通信
	//并发 两个循环同时进行
	CreateThread(NULL,NULL,
		(LPTHREAD_START_ROUTINE)tongxin,
		(LPVOID)i,
		NULL,NULL);
	}

	//8关闭socket
	closesocket(serverSocket);
	//9清理协议版本信息
	WSACleanup();

	return 0;
}

static int getNumber(const char *s)
{
    int i = 0, j = 0;
    while (s[i])
    {
    	
        if ((s[i] & 0xc0) != 0x80) j++;
        i++;
    }
    return j;
}

void findIP(char *ip, int size) 
{
	WORD v = MAKEWORD(1, 1);
	WSADATA wsaData;
	WSAStartup(v, &wsaData); // 加载套接字库
 
	struct hostent *phostinfo = gethostbyname("");
	char *p = inet_ntoa (* ((struct in_addr *)(*phostinfo->h_addr_list)) ); 				
	strncpy(ip, p, size - 1);
	ip[size - 1] = '\0';
	WSACleanup( );
} 

看到这里的大佬们,代码我纯手打,可能存在bug,欢迎各位指正,也希望你们能为我点一个大大的赞!将这份知识传递下去! 文章来源地址https://www.toymoban.com/news/detail-478757.html

到了这里,关于基于TCP协议的聊天室详细教学(C++)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • QT程序设计多人聊天室(基于QT、sqlite3、TCP/IP)

    目录 技术路线 效果展示 程序主体 sqoperator.h mylogin.h myenroll.h chatinterface.h tips.h myapp.h ******************* sqoperator.cpp mylogin.cpp myenroll.cpp chatinterface.cpp tips.cpp myapp.cpp main.cpp widget.h widget.cpp main.cpp QT程序设计、sqlite数据库调用、TCP/IP客户端与服务端的搭建 通过次程序代码,可以学习如

    2024年02月09日
    浏览(50)
  • LinuxC TCP实现简易聊天室

    目录 1.概述 1.1聊天室设计内容 2.系统设计 2.1系统功能设计 2.1.1用户管理 2.1.2聊天室管理 2.1.3聊天管理 2.2系统数据结构设计 2.3系统主要函数设计 3.系统实现 3.2功能模块的程序流程图及运行界面 3.2.1功能模块流程图  3.2.2运行界面 4.源代码 4.1客户端 4.2服务器 注:存在问题 1

    2024年02月09日
    浏览(29)
  • C语言Socket编程TCP简单聊天室

    这是一个使用C语言进行套接字编程实现的简单聊天室, 使用Pthread库进行多线程执行 服务端: svr.c 客户端: cli.c Makefile: Makefile 执行编译 启动服务器 启动客户端 聊天 退出

    2024年02月03日
    浏览(37)
  • 计算机网络 TCP/UDP程序开发网络聊天室

    TCP/UDP程序开发 开发TCP/UDP协议应用程序,掌握网络应用程序的工作原理。通过该实验,深入理解UDP和TCP协议的异同点,了解网络协议的工作过程,学会网络通信编程的基本方法,能够编制网络应用程序。 (1)了解和掌握“基于UDP-面向无连接的应用程序/基于TCP-面向连接的

    2024年02月05日
    浏览(62)
  • 网络编程 IO多路复用 [select版] (TCP网络聊天室)

    //head.h                 头文件 //TcpGrpSer.c        服务器端 //TcpGrpUsr.c        客户端 select函数  功能:阻塞函数,让内核去监测集合中的文件描述符是否准备就绪,若准备就绪则解除阻塞。 原型: head.h TcpGrpSer.c TcpGrpUsr.c    

    2024年02月14日
    浏览(39)
  • 网络编程 IO多路复用 [epoll版] (TCP网络聊天室)

    //head.h            头文件 //TcpGrpSer.c     服务器端 //TcpGrpUsr.c     客户端 通过IO多路复用实现服务器在单进程单线程下可以与多个客户端交互  API epoll函数  head.h TcpGrpSer.c TcpGrpUsr.c  

    2024年02月11日
    浏览(44)
  • [Socket]Python用UDP协议建立带有私聊功能的网络聊天室-建立聊天工具

    前些天实习面试的时候被面试官问到Socket编程的问题,即“Socket创建和释放的具体过程是什么”,当时答不上来,似乎是涉及到发送和接收缓冲区的问题。由于自己在Socket编程这一块知识较为薄弱,于是写下这篇文章,当作复习下Socket编程知识。 首先,该实验是我在大三上学

    2024年02月03日
    浏览(38)
  • 聊天室(二)__ unipush 推送实现详细教程

    推送作用我就不废话了,能做推送的都知道作用,直接上干货。   Dcloud 开发者实名认证注册账号,绑定对应的 app 信息。 uni-push产品有2个入口: 通过 HBuilderX(3.5.1及其以上版本)进入 打开 HBuilderX,双击项目中的 “manifest.json” 文件,选择“App 模块配置”,向下找到“Push(消息

    2024年02月12日
    浏览(33)
  • 基于WebSocket的在线文字聊天室

    与Ajax不同,WebSocket可以使服务端主动向客户发送响应,本案例就是基于WebSocket的一个在线聊天室,不过功能比较简单,只能满足文字交流。演示如下。 案例学习于b站up主,链接 。这位up主讲的非常清楚,值得去学习。本文属于记录自我学习过程的文章。 项目目录下app.js 项

    2024年02月13日
    浏览(38)
  • 基于UDP实现的网络聊天室

    服务器: 客户端: 运行结果:

    2024年03月08日
    浏览(44)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包