计算机网络课程设计-网络聊天程序的设计与实现

这篇具有很好参考价值的文章主要介绍了计算机网络课程设计-网络聊天程序的设计与实现。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

目录

前言

1 实验题目

2 实验目的

3 实验内容

3.1 客户端

3.1.1 步骤

3.1.2 关键代码

3.2 服务器

3.2.1 步骤

3.2.2 关键代码

4 实验结果与分析

5 代码

5.1 客户端

5.2 服务器


前言

        本实验为计算机网络课程设计内容,基本上所有代码都是根据指导书给的附录写出来的。有些实验需要实现图形界面,但是出于期末考试压力,我所有实验均是在控制台输入输出的,没有花额外时间去学习qt了,有精力的同学可以自学一下qt实现简单的图形界面。同时,该博客内容为部分报告内容,仅为大家提供参考,请勿直接抄袭。另外,本次实验所用平台是dev c++5.11

1 实验题目

        实验一 网络聊天程序的设计与实现

2 实验目的

      使用 WinSock API 的编程,了解 Socket 通信的原理,在此基础上编写一个聊天程序。

3 实验内容

3.1 客户端

3.1.1 步骤

        (1)客户端建立连接后接收服务器分配的通信套接字。

        (2)开启线程处理从服务器发送过来的数据。

        (3)不断循环,接收用户输入,发送数据到服务器。

3.1.2 关键代码

        (1)接收服务器发送的数据的线程函数

void handleRecvData(SOCKET client) {
	while(1) {
		memset(recvBuf,'\0',strlen(recvBuf));
		recvCode= recv(client,recvBuf,sizeof(recvBuf),0);
		if(recvCode==-1) {
			cout<<"接收服务器数据异常!\n";
			closesocket(client);
			WSACleanup();
			break;
		}
		if(!flag)cout<<"\n";
		cout<<recvBuf<<"\n"<<"客户端"<<name<<">";
		flag=0;
	}
}

        (2)main函数

int main() {
	// 接收服务器分配的通信套接字
	err = recv(sockClient, name, sizeof(name), 0);	
	// 开启线程处理从服务器发送过来的数据
	thread t(handleRecvData, sockClient);
	t.detach();
	// 不断循环,接收用户输入,发送数据到服务器
	while (1) {
		memset(sendBuf,'\0',strlen(sendBuf));
		cin>>sendBuf;
		flag=1;
		if(!strcmp(sendBuf,"quit")) {
			send(sockClient,"quit",strlen("quit")+1,0);
			cout<<"通知服务器客户端已关闭连接!\n";
			closesocket(sockClient);
			WSACleanup();
			break;
		}
		err = send(sockClient,sendBuf,strlen(sendBuf)+1,0);
		if(err == -1){
			cout<<"客户端发送数据失败!\n";
			break;
		} 
	}
}

3.2 服务器

3.2.1 步骤

        (1)服务器端初始化,绑定地址并开始监听客户端连接请求。

        (2)接受客户端连接请求,为每个客户端分配套接字,并加入客户端列表。

        (3)开启线程处理客户端发来的数据,同时遍历客户端列表,将接收到的信息发送给其他客户端。

3.2.2 关键代码

        (1)处理客户端主要功能代码

void handleClient(SOCKET client) {
	while(1) {
		memset(recvBuf,'\0',strlen(recvBuf));
		memset(sendBuf,'\0',strlen(sendBuf));
		recvCode= recv(client,recvBuf,sizeof(recvBuf),0);
		cout<<"recvCode :"<<recvCode<<"\n";
		if(recvCode==-1||!strcmp(recvBuf,"quit")) {
			//删除断开连接的客户端
			cout<<"客户端"<<client<<"已关闭连接!\n";
clientList.erase(remove(clientList.begin(),clientList.end(),client));
			closesocket(client);
			cout<<"删除断开连接的 client 后,clientList 包含 client 的个数:"<<clientList.size()<<"\n";
			break;
		} else {
	cout<<"clientList 包含 client 的个数:"<<clientList.size()<<"\n";
		}
		cout<<"接收到客户端"<<client<<"的数据:"<<recvBuf<<"\n";
		for(int i=0; i<clientList.size(); i++) {
			sprintf(sendBuf,"群聊信息---客户端%d>%s",client,recvBuf);
			sendCode = send(clientList[i],sendBuf,strlen(sendBuf)+1,0);
			cout<<"服务器发送数据:\""<<sendBuf<<"\",给客户端"<<clientList[i]<<",sendCode :"<<sendCode<<"\n";
		}
	}
}

        (2)main函数

int main() {
// 循环接受客户端连接请求,为每个客户端分配套接字,加入客户端列表并单独处理
while(1) {
		memset(id,'\0',strlen(id));
		cout<<"等待新客户端连接\n";
		SOCKET sockConn=accept(sockSrv,(SOCKADDR*)&addrClient,&len);
		if(sockConn==-1) {
			cout<<"新客户端连接失败\n";
			closesocket(sockConn);
			closesocket(sockSrv);
			WSACleanup();
		} else {
			cout<<"新客户端连接成功\n";
			sprintf(id,"%d",sockConn);
			sendCode = send(sockConn,id,strlen(id)+1,0);
	cout<<"为新客户端分配套接字:"<<id<<", sendCode :"<<sendCode<<"\n";
			clientList.push_back(sockConn);
			thread t(handleClient,sockConn);
			t.detach();
		}
	}

4 实验结果与分析

(1)启动服务器等待客户端连接。

计算机网络课程设计-网络聊天程序的设计与实现,计算机网络,计算机网络

图1.1 启动服务器

(2)启动3个客户端加入聊天。

计算机网络课程设计-网络聊天程序的设计与实现,计算机网络,计算机网络

图1.2 启动客户端

(3)客户端280发送消息,可以在客户端252和260收到信息。

计算机网络课程设计-网络聊天程序的设计与实现,计算机网络,计算机网络

图1.3 客户端280发送信息文章来源地址https://www.toymoban.com/news/detail-802967.html

5 代码

5.1 客户端

#include <stdio.h>
#include <bits/stdc++.h>
#include<iostream>
#include<string>
#include<sstream>
#include<cstdio>
#include<vector>
#include<thread>
#include <Winsock2.h>

using namespace std;

typedef long long LL;
const int maxn = 100;
const int maxRecv = 128;
const int maxSend = maxRecv + 20;

char name[6]="\0";
int flag = 0;

void handleRecvData(SOCKET client) {
	char recvBuf[maxRecv];
	int recvCode;
	while(1) {
		memset(recvBuf,'\0',strlen(recvBuf));
		recvCode= recv(client,recvBuf,sizeof(recvBuf),0);
//		cout<<"recvCode :"<<recvCode<<"\n";
		if(recvCode==-1) {
			cout<<"接收服务器数据异常!\n";
			closesocket(client);
			//shutdown(client,2);
			WSACleanup();
			break;
		}
//		cout<<"接收的的数据:"<<recvBuf;
		if(!flag)cout<<"\n";
		cout<<recvBuf;
		cout<<"\n";
		flag=0;
//		if(flag) {
//			flag=0;
//		}
//		if(!flag) {
		cout<<"客户端"<<name<<">";
//			cout<<"\n";
//		}
//		cout<<"\n请输入要发送数据:\n";
	}
}

int main() {
	WORD wVersionRequested;
	WSADATA wsaData;
	int err;
	wVersionRequested = MAKEWORD( 1, 1 );

	err = WSAStartup( wVersionRequested, &wsaData );
	if ( err != 0 ) {
		return 0;
	}
	if ( LOBYTE( wsaData.wVersion ) != 1 || HIBYTE( wsaData.wVersion ) != 1 ) {
		WSACleanup();
		return 0;
	}

	SOCKET sockClient=socket(AF_INET,SOCK_STREAM,0);
	if(sockClient==-1) {
		cout<<"创建客户端失败"<<"\n";
		closesocket(sockClient);
		WSACleanup();
		return 0;
	}
	cout<<"创建客户端成功"<<"\n";

	SOCKADDR_IN addrSrv;
	addrSrv.sin_addr.S_un.S_addr=inet_addr("127.0.0.1");
	addrSrv.sin_family=AF_INET;
	addrSrv.sin_port=htons(6000);

	err = connect(sockClient,(SOCKADDR*)&addrSrv,sizeof(SOCKADDR));
	if(err==-1) {
		closesocket(sockClient);
		WSACleanup();
		cout<<"连接服务器失败"<<"\n";
	}
	cout<<"连接服务器成功\n";

	err = recv(sockClient,name,sizeof(name),0);
	if(err==-1) {
		closesocket(sockClient);
		WSACleanup();
		cout<<"获取服务器分配的通信套接字失败"<<"\n";
	}
	cout<<"服务器分配的通信套接字:"<<name<<"\n";
	cout<<"-------------------------------------------\n";

	//开启线程处理从服务器发送过来的数据
	thread t(handleRecvData,sockClient);
	t.detach();

	char sendBuf[maxSend]="\0";
	cout<<"客户端"<<name<<">";
	while(1) {
		memset(sendBuf,'\0',strlen(sendBuf));
//		cout<<"请输入要发送数据:\n";
//		cout<<"客户端"<<name<<">";
		cin>>sendBuf;
		flag=1;
		if(!strcmp(sendBuf,"quit")) {
			send(sockClient,"quit",strlen("quit")+1,0);
			cout<<"通知服务器客户端已关闭连接!\n";
			closesocket(sockClient);
			WSACleanup();
			break;
		}
		err = send(sockClient,sendBuf,strlen(sendBuf)+1,0);
//		cout<<"sendCode :"<<err<<"\n"; 
		if(err == -1){
			cout<<"客户端发送数据失败!\n";
//			closesocket(sockClient);
//			WSACleanup();
			break;
		} 
		//while(flag==1);
//		cout<<"客户端"<<name<<"发送数据:"<<sendBuf<<"\n";
//		char recvBuf[50]="\0";
//		cout<<recv(sockClient,recvBuf,50,0)<<"\n";
//		cout<<"接收到服务器数据:";
//		printf("%s\n",recvBuf);
		//cout<<closesocket(sockClient)<<"\n";
		//WSACleanup();
		//cout<<connect(sockClient,(SOCKADDR*)&addrSrv,sizeof(SOCKADDR))<<"\n";
		//cout<<"服务器连接成功\n";
	}
	closesocket(sockClient);
	WSACleanup();
	return 0;
}

5.2 服务器

#include <stdio.h>
#include <bits/stdc++.h>
#include<iostream>
#include<string>
#include<vector>
#include<thread>
#include <Winsock2.h>
#pragma comment(lib,"ws2_32")
using namespace std;

typedef long long LL;
const int maxn = 100;
const int maxRecv = 128;
const int maxSend = maxRecv + 20;

//SOCKET clientList[maxn];
vector<SOCKET> clientList;

void handleClient(SOCKET client) {
	char recvBuf[maxRecv]="\0";
	char sendBuf[maxSend]="\0";
	int recvCode;
	int sendCode;
	while(1) {
		memset(recvBuf,'\0',strlen(recvBuf));
		memset(sendBuf,'\0',strlen(sendBuf));
		recvCode= recv(client,recvBuf,sizeof(recvBuf),0);
		cout<<"recvCode :"<<recvCode<<"\n";
		if(recvCode==-1||!strcmp(recvBuf,"quit")) {
			//删除断开连接的客户端
			cout<<"客户端"<<client<<"已关闭连接!\n";
			clientList.erase(remove(clientList.begin(),clientList.end(),client));
			closesocket(client);
			//shutdown(client,2);
			cout<<"删除断开连接的 client 后,clientList 包含 client 的个数:"<<clientList.size()<<"\n";
			break;
		} else {
			cout<<"clientList 包含 client 的个数:"<<clientList.size()<<"\n";
		}

		cout<<"接收到客户端"<<client<<"的数据:"<<recvBuf<<"\n";
//		printf("%s\n",recvBuf);

		for(int i=0; i<clientList.size(); i++) {
//			if(clientList[i]==client) {
//				cout<<"跳过 client:"<<client<<"\n";
//				continue;
//			}
			sprintf(sendBuf,"群聊信息---客户端%d>%s",client,recvBuf);
			sendCode = send(clientList[i],sendBuf,strlen(sendBuf)+1,0);
//			sendCode = send(clientList[i],recvBuf,strlen(recvBuf)+1,0);
			cout<<"服务器发送数据:\""<<sendBuf<<"\",给客户端"<<clientList[i]<<",sendCode :"<<sendCode<<"\n";
//			cout<<"sendCode :"<<sendCode<<"\n";
		}
	}
}
int main() {
	WORD wVersionRequested;
	WSADATA wsaData;
	int err;
//	vector<SOCKET> clientList;

	wVersionRequested = MAKEWORD( 1, 1 );

	err = WSAStartup( wVersionRequested, &wsaData );
	if ( err != 0 ) {
		cout<<"初始化套接字库失败"<<"\n";
		return 0;
	}
	cout<<"初始化套接字库成功"<<"\n";
	if ( LOBYTE( wsaData.wVersion ) != 1 || HIBYTE( wsaData.wVersion ) != 1 ) {
		WSACleanup();
		cout<<"确定协议失败"<<"\n";
		return 0;
	}
	cout<<"确定协议成功"<<"\n";
	SOCKET sockSrv=socket(AF_INET,SOCK_STREAM,0);
	if(sockSrv==-1) {
		closesocket(sockSrv);
		WSACleanup();
		cout<<"创建服务器失败"<<"\n";
		return 0;
	}
	cout<<"创建服务器成功"<<"\n";
	cout<<"sockSrv :"<<sockSrv<<"\n";
	SOCKADDR_IN addrSrv;
	//htonl函数把主机字节转化成网络字节的函数;u_long htonl(u_long hostlong);
	addrSrv.sin_addr.S_un.S_addr=htonl(INADDR_ANY);
	addrSrv.sin_family=AF_INET;
	addrSrv.sin_port=htons(6000);

	//绑定
	err = bind(sockSrv,(SOCKADDR*)&addrSrv,sizeof(SOCKADDR));
	if(err==-1) {
		closesocket(sockSrv);
		WSACleanup();
		cout<<"服务器绑定失败"<<"\n";
		return 0;
	}
	cout<<"服务器绑定成功"<<"\n";

	err = listen(sockSrv,5);
	if(err==-1) {
		closesocket(sockSrv);
		WSACleanup();
		cout<<"监听失败"<<"\n";
		return 0;
	}
	cout<<"监听成功"<<"\n";
	cout<<"-------------------------------------------\n";
	
	SOCKADDR_IN addrClient;
	int len=sizeof(SOCKADDR);
	char id[6]="\0";
	int sendCode;
	while(1) {
		memset(id,'\0',strlen(id));
		cout<<"等待新客户端连接\n";
		SOCKET sockConn=accept(sockSrv,(SOCKADDR*)&addrClient,&len);
		if(sockConn==-1) {
			cout<<"新客户端连接失败\n";
			closesocket(sockConn);
			closesocket(sockSrv);
			WSACleanup();
		} else {
			cout<<"新客户端连接成功\n";
//			cout<<"sockConn :"<<sockConn<<"\n";
			sprintf(id,"%d",sockConn);
//			cout<<"分配给新客户端的套接字:"<<id<<"\n";
			sendCode = send(sockConn,id,strlen(id)+1,0);
			cout<<"为新客户端分配套接字:"<<id<<", sendCode :"<<sendCode<<"\n";
			clientList.push_back(sockConn);
			thread t(handleClient,sockConn);
			t.detach();
		}
//		char sendBuf[50];
		cout<<"请输入要发送数据:\n";
		cin>>sendBuf;
//		sprintf(sendBuf,"Welcome %s to here!",inet_ntoa(addrClient.sin_addr));
//		cout<<send(sockConn,sendBuf,strlen(sendBuf)+1,0)<<"\n";
//		cout<<"服务器发送数据:"<<sendBuf<<"\n";
//		char recvBuf[50];
//		cout<<recv(sockConn,recvBuf,50,0)<<"\n";
//		if(!strcmp(recvBuf,"quit")) {
//			cout<<"客户端已关闭连接!";
//			break;
//		} else  {
//			cout<<"接收到客户端数据:";
//			printf("%s\n",recvBuf);
//		}
//		cout<<closesocket(sockConn)<<"\n";
		//cout<<"服务器关闭连接\n";
	}
	//closesocket(sockConn);
	WSACleanup();
	return 0;
}

到了这里,关于计算机网络课程设计-网络聊天程序的设计与实现的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

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

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

相关文章

  • 计算机网络课程实验4——编程实现路由算法(迪杰斯特拉算法)

    实验目的: 运用各种编程语言实现基于 Dijkstra 算法的路由软件。 实验意义: 通过本实验,使学生能够对路由原理和路由算法有进一步的理解和掌握。 实验步骤: 1, 选择合适的编程语言编程实现基于 Dijkstra 算法的路由软件。 输入不同的网络拓扑和链路代价测试和验证自己

    2024年02月06日
    浏览(34)
  • 云计算:计算机网络基础(第二天课程分享)DNS协议 各协议

    HTTP--tcp 80 ----超文本传输协议    HTTPS---tcp 443 安全传输协议  FTP tcp 20/21 文件传输协议    TFTP udp 69 简单文件传输   Telnet TCP 23 远程登录协议   SSH tcp 22 安全外壳协议 DNS UDP/TCP 53 域名解析协议  DHCP UDP 67/68 动态主机配置协议     传输层协议:TCP/UDP TCP-----传输控制协议----

    2024年02月04日
    浏览(31)
  • 计算机网络课程 day1 基本概念-交换机-路由器 计算机网络的参考模型

    目录 学习计算机网络课程的目标和意义:  计算机网络的基本概念 常用网络设备: network device 交换机:组建局域网使用的,将很多电脑连接起来,组成一个局域网络,可以一起打游戏/上网 路由器:实现跨网段通信使用,把网络里的数据从一个地方转发到另一个地方。可以

    2024年02月13日
    浏览(30)
  • 哈工大计算机网络课程传输层协议之:拥塞控制原理剖析

    哈工大计算机网络课程传输层协议详解之:可靠数据传输的基本原理 哈工大计算机网络课程传输层协议详解之:流水线机制与滑动窗口协议 哈工大计算机网络课程传输层协议详解之:TCP协议 **拥塞(Congestion)** 非正式定义:“太多发送主机发送了太多数据或者发送速度太快

    2024年02月11日
    浏览(28)
  • 哈工大计算机网络课程网络层协议详解之:路由算法概述与链路状态路由算法

    在前面的小节中,我们介绍了网络中路由器的路由与转发等功能。我们说 作为网络层,从功能上来说,核心功能就是要实现路由和转发。 对于转发来说,实际上就是路由器根据存储的转发表,将目的地址转发到对应的输出链路上去。在这个过程中,完成转发的重要依据,就

    2024年02月11日
    浏览(30)
  • 哈工大计算机网络课程网络层协议详解之:互联网控制报文协议(ICMP)

    在互联网中,IP数据报的传输很容易出现差错,当出现差错时,最简单的处理办法就是对该IP数据报进行丢弃。但是,并不是直接丢弃就完了,为了让源主机感知到数据报出现差错,当数据报被丢弃时,IP网络会借助于ICMP协议,向发送数据报的源主机发送一个ICMP差错报文。本

    2024年02月12日
    浏览(34)
  • 哈工大计算机网络课程局域网详解之:无线局域网

    本节介绍一下平时经常使用的一个无线局域网技术,也就是通常我们使用的wifi。 wifi是IEEE 802.11这样一个系列标准所定义的无线局域网。作为802.11局域网来说,实际上存在很多版本: 802.11b 2.4-2.5GHz免费频段(unliebensed spectrum) 最高速率:11Mbps 物理层采用直接序列扩频(DSSS)

    2024年02月15日
    浏览(33)
  • 哈工大计算机网络课程局域网详解之:交换机概念

    在介绍完局域网中最具代表性的以太网技术后,接下来我们继续来看一下在局域网中使用非常广泛也是非常重要的网络设备:交换机。 本节主要面向以太网来介绍其中使用的交换机。 作为以太网交换机来说,是一个典型的数据链路层设备,可以实现对链路层数据帧的存储-转

    2024年02月15日
    浏览(33)
  • 哈工大计算机网络课程网络安全基本原理详解之:消息完整性与数字签名

    这一小节,我们继续介绍网络完全中的另一个重要内容,就是消息完整性,也为后面的数字签名打下基础。 首先来看一下什么是报文完整性。 报文完整性,也称为消息完整性(message integrity),有时也称为报文/消息认证(或报文鉴别),目标: 证明报文确实来自声称的发送

    2024年02月15日
    浏览(28)
  • 哈工大计算机网络课程数据链路层协议详解之:多路访问控制(MAC)协议

    在上一小节介绍完数据链路层功能和所提供的服务后,接下来我们介绍一个在 数据链路层非常重要的一个协议:多路访问控制MAC协议。 多路访问控制主要是为了解决一类链路的使用问题。作为网路中的链路,大致可以分为以下两类: 点对点链路 顾名思义,链路只连接两个相

    2024年02月15日
    浏览(33)

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

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

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

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

二维码1

领取红包

二维码2

领红包