网络编程 基于TCP的简易聊天室 实验报告
网上聊天 实验报告
C/S网络聊天室程序----实验报告信科03(1)班楼欢庆I03630117 聊天室程序的设计说明1.实现思想在Internet上的聊天室程序一般都是以服务器提供服务端连接响应,使用者通过客户端程序登录到服务器,就可以与登录在同一服务器上的用户交谈,这是一个面向连接的通信过程。
因此,程序要在TCP/IP环境下,实现服务器端和客户端两部分程序。
实现语言C++,开发环境VC/MFC。
2.功能模块总纲2.1服务器端工作流程服务器端通过socket()系统调用创建一个Sock et数组后(即设定了接受连接客户的最大数目),与指定的本地端口绑定bind(),就可以在端口进行侦听listen()。
如果有客户端连接请求,则在数组中选择一个空Socket,将客户端地址赋给这个Socket。
然后登录成功的客户就可以在服务器上聊天了。
实现方式采用异步非阻塞机制。
2.2客户端工作流程客户端程序相对简单,只需要建立一个Socket 与服务器端连接,成功后通过这个Socket来发送和接收数据就可以了。
2.3 C/S实现过程服务器端:<1>首先使用WSAStartup函数来初始化网络环境。
<2>调用socket(AF_INET,SOCK_STREAM,0)函数来创建一个套接字。
<3>调用bind函数将本地地址与刚建立的套接字关联起来。
<4>调用listen函数监听发向该套接字的连接请求。
<5>客户端的连接请求放在连接请求队列里,服务器调用accept函数从连接请求队列中取出第一个请求,创建一个为之服务的新的套接字,该套接字处理所有与该客户交互操作的信息。
而服务器进程的监听套接字这时继续处理来自其他客户的连接请求,直到因队列空而等待新的连接请求的到来。
<6>调用closesocket()关闭监听套接字,释放套接字资源。
<7>调用WSACleanup函数释放相应资源。
网络编程_实验报告
一、实验目的1. 理解网络编程的基本原理和概念。
2. 掌握TCP/IP协议的基本工作原理。
3. 学会使用Socket编程实现网络通信。
4. 增强实际操作能力,提高网络编程水平。
二、实验环境1. 操作系统:Windows 102. 编程语言:Python3.83. 开发工具:PyCharm4. 网络环境:校园局域网三、实验内容本次实验主要实现一个基于TCP协议的简单网络通信程序,包括客户端和服务器端。
1. 服务器端服务器端负责监听客户端的连接请求,接收客户端发送的数据,并回显给客户端。
```pythonimport socket# 创建socket对象server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)# 获取本地主机名host = socket.gethostname()port = 12345# 绑定端口server_socket.bind((host, port))# 设置最大连接数,超过后排队server_socket.listen(5)print("等待客户端连接...")while True:# 建立客户端连接client_socket, addr = server_socket.accept()print("连接地址:", addr)while True:# 接收客户端数据data = client_socket.recv(1024)if not data:break# 发送数据回客户端client_socket.send(data)# 关闭连接client_socket.close()```2. 客户端客户端负责向服务器端发送数据,并接收服务器端回显的数据。
```pythonimport socket# 创建socket对象client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)# 获取本地主机名host = socket.gethostname()port = 12345# 连接服务器client_socket.connect((host, port))# 发送数据client_socket.send("Hello, Server!")# 接收数据data = client_socket.recv(1024)print("从服务器接收到的数据:", data)# 关闭连接client_socket.close()```四、实验步骤1. 编写服务器端代码,并运行程序。
网络编程实验报告
简单的聊天室程序电子信息系1 设计目的综合运用本课程及计算机网络的相关知识设计并实现一个网络应用程序,以Visual C++作为开发平台,通过实践复习巩固课堂所学的理论知识,提高对所学知识的综合应用能力。
2 实验要求采用客户/服务器模式,分为客户端程序和服务器端程序。
服务器采用WINSOCK I/O 模型中的任一种,支持多个客户同时在线聊天。
客户端程序和服务器程序通过网络交换聊天字符串内容,服务器窗口的列表框中显示当前在线用户,支持客户端之间的私聊(可以通过服务器中转,或考虑UDP打洞直接建立端端连接)。
实验要求设计并编程完成两个方面的内容:首先建立一个使用TCP协议的聊天室服务器,这个服务器可以同时支持多个用户的在线聊天;其次设计一个可以和服务器通信的聊天室客户端。
3 功能要求✧支持多个客户端的连接,在服务器和多个客户端之间进行数据传输;✧接收客户端发送的消息,并显示在一个列表框中;✧在用户连接上后有提示,显示出连接的用户名字;✧发送信息时可以显示聊天的所有记录;4 系统主要功能和主要功能描述:服务器端聊天程序必须能够做3件事情:(1)服务器聊天程序要在待定的端口上等待来自聊天客户的连接请求,并且需要维护一个客户连接表,以记录所有成功的连接。
(2)服务器聊天程序要及时接受从各个聊天客户发送过来的信息,然后把这些信息转发到一个或多个客户连接。
对于公共聊天室,服务器将把接受到的信息向除源端外的所有客户发送过去。
(3)服务器还要监控这些连接的状态,在客户主动离开或发生故障时从列表中删除相应的表项,并及时更新连接表。
这些要求可以通过CSocket类提供的功能实现。
从CSocket派生出两个类CListenSocket和CClientSocket,它们分别用来侦听客户的连接请求和建立与客户的连接。
服务器只需要一个侦听套接字CListenSocket,然后根据客户的连接请求动态创建客户套接字CClientSocket。
TCP聊天系统实验报告
信息管理系《计算机网络》课程设计报告学生姓名:王法芝,王敏学号:***************222009602063010 专业班级:2009级信管1班成绩:指导教师:***二0一一年11 月 6 日目录一、背景分析: (3)二、需求分析: (3)三、开发流程: (5)四、具体实现过程: (5)一、客户端发送消息不能为空。
(5)二、在消息后面加上了发送消息的时间 (5)四、添加用户表情: (6)五、系统结构: (6)四、界面: (9)1、最初界面为: (9)2、聊天时的界面为: (9)六、程序的不足之处(尚未实现之处): (10)七、总结: (10)八、参考文献: (10)开发报告一、背景分析:本次实验基于VC++6.0平台,应用MFC和SOCKET编程技术,实现聊天室(chat server and client)的功能添加和功能实现。
关于WinSocket和MFC的一点理解和体会:Socket接口是网络编程(通常是TCP/IP协议,也可以是其他协议)的API。
WinSock以DLL的形式提供。
WinSock也是一个基于Socket模型的API,在Microsoft Windows操作系统类中使用。
Socket是网络通信过程中端点的抽象表示。
Socket在实现中以句柄的形式被创建,包含了进行网络通信必须的五种信息:连接使用的协议,本地主机的IP地址,本地进程的协议端口,远地主机的IP地址,远地进程的协议端口。
要使用socket,首先必须创建一个socket;然后,按要求配置socket;接着,按要求通过socket接收和发送数据;最后,程序关闭此socket。
实现Windows Sockets应用程序在网上的数据通信,必须在Windows 9x/NT 控制面板中的网络配置项里,添加TCP/IP协议,同时给定相应的IP地址,这些IP地址在所建的局域网中,不能有重复,一般要采用C类地址。
Windows 9x/NT带有协议。
python基于tcp_协议实现智能聊天机器人的实验报告总结
python基于tcp 协议实现智能聊天机器人的实验报告总结1. 引言1.1 概述本实验报告总结了基于TCP协议实现的智能聊天机器人的设计、实现和测试过程。
智能聊天机器人是一种具备自主对话能力的计算机程序,可模拟真实人类对话,并为用户提供各种服务和答案。
本次实验旨在通过利用Python语言编写服务器端和客户端程序,基于TCP协议实现一个智能聊天机器人系统。
1.2 文章结构本篇文章共分为六个部分:引言、TCP协议和Python简介、智能聊天机器人原理与设计、基于TCP协议的智能聊天机器人实现过程、实验结果与分析以及结论与展望。
具体内容分别包括对TCP协议和Python语言的简要介绍,智能聊天机器人的原理、设计思路和功能模块介绍,以及详细阐述实现过程和系统交互方式。
此外,还将展示对系统功能、性能以及用户反馈进行的测试和评价,并总结实验结果。
最后,将讨论项目存在的问题并提出改进方向,同时对未来智能聊天机器人的发展进行展望。
1.3 目的本次实验报告旨在深入探究TCP协议和Python语言在实现智能聊天机器人方面的应用,并评估系统的功能和性能。
通过这次实验,我们希望能够了解TCP 协议的基本概念和特点,掌握Python语言在网络编程方面的基本知识,理解智能聊天机器人的设计原理和实现方法。
同时,通过实验结果和用户反馈数据的分析,进一步改进系统性能,并对未来智能聊天机器人技术发展进行展望。
2. TCP协议和Python简介:2.1 TCP协议概述TCP(Transmission Control Protocol,传输控制协议)是一种面向连接、可靠的传输层协议。
它通过在通信双方之间建立起可靠的数据传输连接来提供端到端的数据传输服务。
TCP协议采用三次握手来建立连接,并使用序列号和确认应答机制来保证可靠性。
此外,TCP还具有流量控制和拥塞控制等机制,以实现高效稳定的数据传输。
2.2 Python对于网络编程的支持Python是一种强大且广泛使用的编程语言,它提供了丰富的库和模块用于网络编程。
网络编程实训大作业报告
一、引言随着信息技术的飞速发展,网络编程已经成为计算机科学与技术领域的一个重要分支。
为了提高我们的实际动手能力和理论联系实际的能力,我们选择了网络编程实训作为本次大作业。
通过本次实训,我们不仅掌握了网络编程的基本知识,还锻炼了团队协作和解决问题的能力。
以下是本次实训的大作业报告。
二、实训背景与目标1. 实训背景随着互联网的普及,网络编程技术在各个领域都得到了广泛应用。
为了提高我们的网络编程技能,我们选择了网络编程实训作为本次大作业。
2. 实训目标(1)掌握网络编程的基本概念和原理;(2)熟悉常用的网络编程技术,如TCP/IP、HTTP等;(3)掌握编程工具的使用,如Visual Studio、NetBeans等;(4)提高团队协作和解决问题的能力。
三、实训内容1. 项目概述本次实训大作业要求我们设计并实现一个基于TCP协议的简易聊天室。
该聊天室能够实现多用户同时在线聊天,用户之间可以发送文本消息。
2. 技术选型(1)编程语言:Java;(2)网络协议:TCP/IP;(3)开发工具:NetBeans;(4)数据库:无。
3. 功能模块(1)客户端模块:负责接收用户输入的消息,并将消息发送给服务器;同时,接收服务器发送的消息,显示在聊天窗口中。
(2)服务器模块:负责接收客户端发送的消息,并将消息广播给所有在线用户;同时,处理客户端的登录、注册等请求。
4. 实现步骤(1)搭建开发环境:安装Java、NetBeans等开发工具;(2)设计客户端界面:使用Swing组件设计聊天窗口、输入框、发送按钮等;(3)编写客户端代码:实现用户登录、注册、发送消息等功能;(4)编写服务器端代码:实现消息广播、用户管理等功能;(5)测试与调试:在本地环境中运行程序,进行功能测试和性能测试;(6)优化与完善:根据测试结果,对程序进行优化和改进。
四、实训成果与总结1. 成果展示本次实训大作业成功实现了一个基于TCP协议的简易聊天室,功能如下:(1)用户登录:用户可以通过用户名和密码登录聊天室;(2)发送消息:用户可以在聊天窗口中输入消息,点击发送按钮将消息发送给所有在线用户;(3)接收消息:用户可以接收其他用户发送的消息,并在聊天窗口中显示;(4)用户管理:管理员可以管理在线用户,包括查看在线用户列表、封禁用户等。
设计聊天室实验报告
write( sockfd, str, strlen( str));
fcntl( 0, F_SETFL, O_NONBLOCK);
while ( 1) {
if ( (status = read( sockfd, str, MAX_LINE))>=0 )
{
if ( status == 0) exit(0);
sizeof( serv_addr))<0) {
printf( "client:can`t connect to server\n");
fflush( stdout);
return( 0);
}
return( sockfd);
}
运行结果:
服务器端运行结果,显示端口号并处于等待连接状态:
群聊功能,四个客户端代表四个用户,通过服务器的转发实现通信。
#include<>
#include<>
#include <>
#include <netinet/>
#include <>
#include <>
#include <>
#define MAX_LINE 500
#define MAX_NAME 100
int init_cli();
#ifndef __SELECT__
实验内容
(1)编写聊天室的客户端和服务器端,客户端主要功能是发送信息,服务器端的主要功能是将客户端发的内容转发到除发送端以外的所有客户端,实现客户端和客户端的通信。
(2)编写基于原始套接字的网络通信原型系统;
(完整)计算机网络TCP聊天室实验报告
计算机网络原理实验报告书姓名:XXX班级:XXXXXX学号:XXXXXXXXXXXXXXXXXXXXXX二0一一年五月socket编程一、实验目的本次实验的目的是通过利用Socket编写简单的客户/服务器程序,了解TCP/IP网络的基本通信原理和编程方法,初步掌握TCP/IP网络的传输层上的编程接口(Windows Sockets API),学会利用这些接口来编写简单的网络通信软件。
二、实验内容利用socket编写简单的客户/服务器程序,比如聊天室、文件传输等。
三、实验步骤➢思路分析✧将服务器与客户端分两部分实现,采用多线程实现多个客户端与服务器端连接✧客户端建立一个Socket与服务器端连接,成功后通过这个Socket来发送和接收数据就可以了。
✧服务器端通过创建一个Socket的Arraylist数组,与指定的本地端口绑定,就可以在端口进行侦听.如果有客户端连接请求,则在数组中选择一个空Socket,将客户端地址赋给这个Socket。
然后登录成功的客户就可以在服务器上聊天了.➢代码实现➢p ackage TCP_chat_room。
gui;➢➢i mport java.io。
IOException;➢➢p ublic class ClientApp {➢public static void main(String[] args){➢/**➢ * javax.swing。
UIManager$LookAndFeelInfo[Metal javax.swing。
plaf。
metal.MetalLookAndFeel]➢javax。
swing。
UIManager$LookAndFeelInfo[Nimbus com.sun。
java.swing.plaf。
nimbus.NimbusLookAndFeel]➢javax。
swing.UIManager$LookAndFeelInfo[CDE/Motif com.sun。
计算机网络课设基于TCP协议编程的网络聊天室
基于TCP协议编程的网络聊天室设计内容: 基于TCP协议编程的方式, 编写程序模拟网络聊天室的运营过程。
设计规定:1.采用C/S模式,基于TCP协议编程的方式,使得各个用户通过服务器转发实现聊天的功能。
2.分为两大模块: 客户端模块和服务器端模块。
3.客户端模块的重要功能:1)登陆功能:用户可以注册, 然后选择服务器登入聊天室。
2)显示用户: 将在线用户显示在列表中。
3)接受信息: 能接受其他用户发出的信息。
4)发送信息: 能发出用户要发出的信息。
4.服务器端模块的重要功能:1)检查登陆信息:检查登陆信息是否对的, 并向客户端返回登陆信息,如信息对的。
就允许用户登陆。
2)显示在线状态: 将该用户的状态发给各在线用户。
一、3)转发聊天信息: 将消息转发给所有在线的用户。
二、 5.编程语言不限。
三、需求分析此程序重要分为两部分: 服务器端和客户端。
服务器端用于提供一个网络端口, 等待客户端发出请求, 登录到此服务端, 然后进行网络通讯和消息的转发;客户端可通过服务器端的IP地址发送连接请求, 然后登陆聊天室。
在服务器端的成员列表栏中会显示在线的所有人名单, 有人退出聊天室, 成员列表会自动除名。
整个程序的主体使用了CSocket 类的方法, 实现了网络通讯聊天。
整个程序设计为两个部分: 服务器(SpeakerServer)和客户端 (SpeakerClient) 。
多人聊天的关键在于要将每个客户端发送过来的消息分发给所有其他客户端, 为了解决这个问题, 在服务器程序中建立一个套接口链表, 用来保存所有与客户端建立了连接的服务端口。
设计原理: 服务器通过socket()系统调用创建一个Socket数组后(设定了接受连接客户的最大数目), 与指定的本地端口绑定bind(), 就可以在端口进行侦听listen()。
假如有客户端连接请求, 则在数组中选择一个空socket, 将客户端地址赋给这个socket, 然后登陆成功的客户就可以在服务器上聊天了。
网络聊天室实现报告
一、背景知识在传统生活里,人们利用写信、电话等方式联络,但此类方式周期缓慢,呆板且不可靠。
在这个信息极其发达的时代,随后我们可以用来进行信息交流的方法日益增多,比如电报、电话、电子邮件、OICQ等通讯手段,但是这些或者不方便或者有局限性或者有费用的问题。
近年来计算机技术的快速发展,特别是计算机网络的发展,越来越深刻的改变了人们生活的方方面面,使得人们能以更低廉的价格,开发出更方便、更实用的网络工具。
各种在线服务系统,更是深刻的影响了人们的联系和交流方式,使得人们可以在远隔千里之遥随时通讯。
过去的种种陈旧的联系方式,已经不能满足现代生活的需要。
网络聊天室凭借其友好的外观、强大的功能、使用的便利、联系的及时等特点博得现代人的青睐,其应用的市场十分广阔。
本系统使用的是C/S模式,使用C#进行聊天室的设计与开发。
本文主要介绍了所应用到的技术的基础知识,并探讨了建立聊天室的设计思想、方法与功能实现流程图。
本文所实现的聊天室具有良好的人机交互界面、合理的数据库结构可以实现发言、自动显示所在聊天室的成员等交互功能,经过测试调试,证明可实际应用。
下图为网络聊天室的主界面图1 网络聊天室主运行界面图二、核心算法思想实现一个基于Socket的简易的聊天室,实现的思路如下:聊天室服务器端启动服务器时,将创建侦听套接字,创建用户列表,创建并启动侦听线程。
用户登录时,将创建套接字,与服务器直接连接,并创建客户端接收线程。
服务器端侦听到有用户上线后,将创建新的用户节点,并在主界面上显示用户上线,发送新的用户列表。
客户端发送信息时,将要发送的内容进行发送。
服务器端发送信息时,如果是发送给所有人,就遍历用户链表,如果是发送给某个用户,先在链表中找到该节点,再发送信息。
服务器端和客户端接收信息时,先读取聊天信息标识,做出判断后,依次读取信息,处理信息,并在主界面上显示,服务器端还要将准备好的信息发送给指定的用户。
开启客户端主界面后,就会启动文件接收侦听线程,如果有用户发送文件至此,将会有信息提示,确定接收后,将启动文件接收线程,对方用户端将启动文件发送线程。
聊天程序设计实验报告范文
聊天程序设计实验报告范文JAVA语言,聊天室实验报告某某专业名称实验室实验课程实验名称姓名学号同组人员实验日期某某某某大学软件工程2号实验楼201室JAVA高级程序设计聊天程序设计(客户端、服务端)无2022年12月12日JAVA语言,聊天室实验报告一、实验目的掌握基于TCP、UDP协议的聊天服务器端与客户端程序设计,掌握Socket,ServerSocket,DatagramSocket,DatagramPacket类的使用。
二、实验原理TCP和UDP协议的支持。
ServerSocket和Socket的使用。
三、实验内容实验截图JAVA语言,聊天室实验报告代码importjava.awt.Point;importjava.io.BufferedReader; importjava.io.IOE某ception; importjava.io.InputStreamReader; importjava.io.PrintWriter;import.ServerSocket;import.Socket;importjava.te某t.DateFormat; importjava.util.Date;importjava.util.HahMap;importjava.util.Vector;importjava.util.logging.Level; importjava.util.logging.Logger;/某某某某/publicclae某tendjava某.wing.JFrame{privateServerSocketerver;privateint=0;privatechar[]chatBuf=newchar[2048]; privateStringchatIpAddre="127.0.0.1"; privatefinalintchatPort=5200;privateHahMap<String,Vector<IMeage>>chatRecordMap;//privateHahMap<String,Integer>chatRecordHMap; publicTalkHome(){chatRecordMap=newHahMap<String,Vector<IMeage>>();//chatRecordHMap=newHahMap<String,Integer>();try{erver=newServerSocket(Integer.valueOf(chatPort));}catch(IOE某ceptione某){Logger.getLogger(TalkHome.cla.getName()).log(Level.SEVERE, null,e某);}newThread(newRunnable(){publicvoidrun(){while(true){try{Socketocket=erver.accept();JAVA语言,聊天室实验报告BufferedReaderin=newBufferedReader(newInputStreamReader(ocket.getInputStream()));inttmp_len=-1;StringBuilderchatStrBuilder=newStringBuilder();while((tmp_len=in.read(chatBuf))!=-1){chatStrBuilder.append(chatBuf,0,tmp_len);}addMeage(ocket.getInetAddre().getHotAddre(),chatStrBuilder.toString(),fale);in.cloe();ocket.cloe();}catch(IOE某ceptione某){Logger.getLogger(TalkHome.cla.getName()).log(Level.SEVERE,nu ll,e某);}}}).tart();}privatevoidreChatWindow(StringipAddre){Sytem.out.println(ipAddre);Vector<IMeage>chatRecord=chatRecordMap.get(ipAddre); jTe某tArea1.etTe某t("");if(chatRecord==null){chatRecord=newVector<IMeage>();chatRecordMap.put(ipAddre,chatRecord);}ele{for(IMeageiMe:chatRecord){if(iMe.imyelf){jTe某tArea1.append("我"+iMe.dateString+"}ele{jTe某tArea1.append("TA"+iMe.dateString+"}}}privatevoidaddMeage(finalStringipAddre,StringmeString,boolea nimyelf){Vector<IMeage>chatRecord=chatRecordMap.get(ipAddre);if(chatRecord==null){JAVA语言,聊天室实验报告chatRecord=newVector<IMeage>();chatRecordMap.put(ipAddre,chatRecord);}finalIMeageiMeage=newIMeage(meString,imyelf);chatRecord.add(iMeage);if(imyelf){newThread(newRunnable(){publicvoidrun(){try{SocketendMeage=newSocket(ipAddre,chatPort);PrintWriterendWindow=newPrintWriter(endMeage.getOutputStream());endWindow.print(iMeage.meString);endWindow.fluh();endWindow.cloe();endMeage.cloe();jTe某tArea1.append("我"+iMeage.dateString+"}catch(IOE某ceptione某){Logger.getLogger(TalkHome.cla.getName()).log(Level.SEVERE,nu ll,e某);}}}).tart();}ele{jTe某tArea1.append("TA"+iMeage.dateString+"}}jCheckBo某1=newjava某.wing.JCheckBo某();jScrollPane2=newjava某.wing.JScrollPane();jTe某tArea2=newjava某.wing.JTe某tArea();jButton2=newjava某.wing.JButton();jFormattedTe某tField1=newjava某.wing.JFormattedTe某tField();jFormattedTe某tField2=newjava某.wing.JFormattedTe某tField();jLabel1=newjava某.wing.JLabel();jLabel2=newjava某.wing.JLabel();JAVA语言,聊天室实验报告jPanel3=newjava某.wing.JPanel();jLabel3=newjava某.wing.JLabel();jScrollPane3=newjava某.wing.JScrollPane();jTe某tArea1=newjava某.wing.JTe某tArea();jCheckBo某1.etTe某t("jCheckBo某1");etDefaultCloeOperation(java某.wing.WindowContant.E某IT_ON_CLOSE);etBackground(newjava.awt.Color(255,255,255));etBound(newjava.awt.Rectangle(0,0,520,520));etCuror(newjava.awt.Curor(java.awt.Curor.DEFAULT_CURSOR));etModalE某cluionType(java.awt.Dialog.ModalE某cluionType.APPLICATION_E某CLUDE);jTe某tArea2.etColumn(20);jTe某tArea2.etFont(newjava.awt.Font("微软雅黑",0,14));//NOI18NjTe某tArea2.etLineWrap(true);jTe某tArea2.etRow(5);jScrollPane2.etViewportView(jTe某tArea2);jButton2.etTe某t("发送");jButton2.addActionLitener(newjava.awt.event.ActionLitener(){ publicvoidactionPerformed(java.awt.event.ActionEventevt){jButton 2ActionPerformed(evt);}});jFormattedTe某tField1.etTe某t("127.0.0.1");jFormattedTe某tField1.etToolTipTe某t("");jFormattedTe某tField2.etTe某t("5200");jFormattedTe某tField2.etToolTipTe某t("");jLabel1.etTe某t("IP:");jLabel2.etTe某t(":");jPanel3.etBackground(newjava.awt.Color(255,255,255));JAVA语言,聊天室实验报告}});jLabel3.etTe某t("对方IP:");jLabel3.etToolTipTe某t("");java某.wing.GroupLayoutjPanel3Layout=newjava某.wing.GroupLayout(jPanel3);jPanel3.etLayout(jPanel3Layout);jPanel3Layout.etHorizontalGroup(jPanel3Layout.createParallelGroup(java某.wing.GroupLayout.Alignment.LEADING).addGroup(jPanel3Layout.createSequentialGroup() .addContainerGap().addPreferredGap(ponentPlacement.UNRELATED)java某.wing.GroupLayout.PREFERRED_SIZE,131,java某.wing.GroupLayout.PREFERRED_SIZE).addContainerGap(java某.wing.GroupLayout.DEFAULT_SIZE,Short.MA某_VALUE)) );jPanel3Layout.etVerticalGroup(jPanel3Layout.createParallelGroup(java某.wing.GroupLayout.Alignment.LEADING).addGroup(jPanel3Layout.createSequentialGroup() .addGap(22,22,22).addGroup(jPanel3Layout.createParallelGroup(java 某.wing.GroupLayout.Alignment.BASELINE)java某.wing.GroupLayout.PREFERRED_SIZE,java某.wing.GroupLayout.DEFAULT_SIZE,java某.wing.GroupLayout.PREFERRED_SIZE).addContainerGap(java某.wing.GroupLayout.DEFAULT_SIZE,Short.MA某_VALUE)) );jTe某tArea1.etEditable(fale);jTe某tArea1.etColumn(20);JAVA语言,聊天室实验报告jTe某tArea1.etFont(newjava.awt.Font("微软雅黑",0,14));//NOI18NjTe某tArea1.etLineWrap(true);jTe某tArea1.etRow(5);jScrollPane3.etViewportView(jTe某tArea1);java某.wing.GroupLayoutlayout=newjava某.wing.GroupLayout(getContentPane());getContentPane().etLayout(layout);layout.etHorizontalGroup(layout.createParallelGroup(java某.wing.GroupLayout.Alignment.LEADING).addGroup(java某.wing.GroupLayout.Alignment.TRAILING,layout.createSequentialGroup().addGroup(layout.createParallelGroup(java某.wing.GroupLayout.Alignment.LEADING).addGroup(java某.wing.GroupLayout.Alignment.TRAILING,layout.createSequentialGr oup().addGap(2,2,2).addPreferredGap(ponentPlacement.RELATED)java某.wing.GroupLayout.PREFERRED_SIZE,104,java某.wing.GroupLayout.PREFERRED_SIZE).addPreferredGap(ponentPlacement.RELATED)java某.wing.GroupLayout.PREFERRED_SIZE,6,java某.wing.GroupLayout.PREFERRED_SIZE).addPreferredGap(ponentPlacement.RELATED)java某.wing.GroupLayout.PREFERRED_SIZE,43,java某.wing.GroupLayout.PREFERRED_SIZE).addPreferredGap(ponentPlacement.RELATED,123,Short.MA某_VALUE).addPreferredGap(ponentPlacement.RELATED)java某.wing.GroupLayout.PREFERRED_SIZE)JAVA语言,聊天室实验报告.addContainerGap()));layout.etVerticalGroup(layout.createParallelGroup(java某.wing.GroupLayout.Alignment.LEADING).addGroup(layout.createSeq uentialGroup().addGroup(layout.createParallelGroup(java某.wing.GroupLayout.Alignment.LEADING,fale)java某.wing.GroupLayout.DEFAULT_SIZE,java某.wing.GroupLayout.DEFAULT_SIZE,Short.MA某_VALUE)java某.wing.GroupLayout.DEFAULT_SIZE,358,Short.MA某_VALUE)) .addPreferredGap(ponentPlacement.RELATED)java某.wing.GroupLayout.DEFAULT_SIZE,131,Short.MA某_VALUE) .addPreferredGap(ponentPlacement.RELATED).addGroup(layout.createParallelGroup(java某.wing.GroupLayout.Alignment.BASELINE)java某.wing.GroupLayout.PREFERRED_SIZE,java某.wing.GroupLayout.DEFAULT_SIZE,java某.wing.GroupLayout.PREFERRED_SIZE)java某.wing.GroupLayout.PREFERRED_SIZE,java某.wing.GroupLayout.DEFAULT_SIZE,java某.wing.GroupLayout.PREFERRED_SIZE).addGap(2,2,2)));pack();}//</editor-fold>addMeage(chatIpAddre,jTe某tArea2.getTe某t(),true);jTe某tArea2.etTe某t("");}if(evt.getStateChange()==1){JAVA语言,聊天室实验报告chatIpAddre=evt.getItem().toString();reChatWindow(chatIpAddre);}}privatePoint;/某某某/publictaticvoidmain(Stringarg[]){try{for(java某.wing.UIManager.LookAndFeelInfoinfo:java某.wing.UIManager.getIntalledLookAndFeel()){if("Nimbu".equal(info.getName())){java某.wing.UIManager.etLookAndFeel(info.getClaName());break;}}}catch(ClaNotFoundE某ceptione某){java.util.logging.Logger.getLogger(TalkHome.cla.getName()).l og(java.util.logging.Level.SEVERE,null,e某);}catch(IntantiationE某ceptione某){java.util.logging.Logger.getLogger(TalkHome.cla.getName()).l og(java.util.logging.Level.SEVERE,null,e某);}catch(IllegalAcceE某ceptione某){java.util.logging.Logger.getLogger(TalkHome.cla.getName()).l og(java.util.logging.Level.SEVERE,null,e某);}catch(java某.wing.UnupportedLookAndFeelE某ceptione某){java.util.logging.Logger.getLogger(TalkHome.cla.getName()).l og(java.util.logging.Level.SEVERE,null,e某);}//</editor-fold>/某Createanddiplaytheform某/java.awt.EventQueue.invokeLater(newRunnable(){publicvoidrun(){newTalkHome().etViible(true);}});JAVA语言,聊天室实验报告}//Variabledeclaration-donotmodifyprivatejava某.wing.JButtonjButton2;privatejava某.wing.JCheckBo某jCheckBo某1;privatejava某.wing.JFormattedTe某tFieldjFormattedTe某tField1;privatejava某.wing.JFormattedTe某tFieldjFormattedTe某tField2;privatejava某.wing.JLabeljLabel1;privatejava某.wing.JLabeljLabel2;privatejava某.wing.JLabeljLabel3;privatejava某.wing.JPaneljPanel3;privatejava某.wing.JScrollPanejScrollPane2;privatejava某.wing.JScrollPanejScrollPane3;privatejava某.wing.JTe某tAreajTe某tArea1;privatejava某.wing.JTe某tAreajTe某tArea2;}claIMeage{publicbooleanimyelf;publicStringmeString;publicIMeage(Stringme,booleanimyelf){thi.imyelf=imyelf;thi.meString=me;}四、实验心得其实java已经将TCP和UDP协议高度封装了,熟练使用ServerSocket和Socket,DataGram会写出想要的网络程序,并不是很难。
设计聊天室实验报告
设计聊天室实验报告一、实验目的本实验的目的是设计一个基于网络的聊天室,实现多用户之间的实时聊天功能。
通过这个实验,我们可以更好地理解计算机网络通信的原理和网络编程的基本知识,同时提高我们的编程能力和团队协作能力。
二、实验内容1.搭建网络环境首先,我们需要搭建一个网络环境,使得多个用户可以通过网络进行通信。
我们选择使用Socket编程,通过TCP/IP协议进行通信。
我们使用Python语言进行编程,通过socket模块中的函数来创建网络连接。
2.实现用户注册和登录功能在聊天室中,每个用户都需要有自己的账户并进行登录操作。
在实验中,我们使用MySQL数据库来存储用户的账户信息。
用户可以通过注册功能来创建自己的账户,并使用登录功能进行登录。
在用户登录成功后,系统将会为其分配一个唯一标识符,并将其保存在服务端。
3.实现聊天功能在登录成功后,用户可以进入聊天室进行聊天操作。
用户可以发送消息给其他用户,并且可以实时接收其他用户发送的消息。
在实现聊天功能时,我们使用多线程的方式,使得每个用户可以同时进行收发消息的操作。
同时,为了保证消息的有序性,我们使用队列来存储用户发送的消息,并使用互斥锁来保护队列的访问。
4.实现用户列表功能为了方便用户之间的选择和通信,我们实现了用户列表功能。
用户可以查看当前在线的用户,并选择要发送消息的目标用户。
在用户列表中,我们显示用户的昵称和状态信息。
三、实验结果通过本次实验,我们成功实现了基于网络的聊天室,并且完成了所有的实验内容。
实际测试中,我们模拟多个用户在不同的终端进行登录和聊天操作,并得到了预期的结果。
用户可以通过注册功能来创建自己的账户,并通过登录功能进行登录。
登录成功后,用户可以进入聊天室进行聊天操作,并可以看到其他用户发送的消息。
同时,用户也可以选择特定的用户进行私聊。
四、实验总结通过本次实验,我们对计算机网络通信的原理和网络编程有了更深入的了解。
我们学会了如何使用Socket编程进行网络连接,并实现了用户注册、登录、聊天和用户列表等功能。
实验八 基于TCP的网络聊天室的设计
实验八基于TCP的网络聊天室的设计1 实验目的(1)掌握通信规范的制定及实现。
(2)练习较复杂的网络编程,能够把协议设计思想应用到现实应用中。
2 实验内容(1)制定通信规范。
(2)设计界面如下:1 服务器端2 客户端(3)设计思路:① TCP/IP数据通信 --- “聊天”消息传输格式客户机 -→服务器(ⅰ)传输“用户名”STX+1+用户名+ETX(ⅱ)悄悄话STX+2+用户名+”,”+内容+ETX(ⅲ)对所有人说STX+3+内容+ETX服务器-→客户机(ⅰ)首次传输在线用户名STX+1+用户名+ETX(ⅱ)传输新到用户名STX+2+用户名+ETX(ⅲ)传输离线用户名STX+3+用户名+ETX(ⅳ)传输聊天数据STX+4+内容+ETX(注:STX为CHR(2),ETX 为CHR(3))②服务器端(ⅰ)定义一个动态数组存储连接用户。
定义一个全局变量存储连接用户的元素个数。
(ⅱ)用一个使用UDP协议的SOCKET套接字完成发送服务器IP地址。
在该控件的数据接收事件中发送服务器IP地址(ⅲ)用一个使用TCP协议的SOCKET套接字数组完成TCP连接及数据发送和接收,处理它的连接请求事件。
(ⅳ)SOCKET套接字的数据到达事件中首先接收数据到一个变量中,然后从这个变量中逐个提取消息,并对每个消息判断消息类型及做相应处理:case 类型1 ……传输“用户名”修改用来存储连接用户的元素个数的数组向所有在线用户发送该用户名消息向该用户发送所有在线用户名的消息case 类型2 ……悄悄话向源和目标用户发送消息case 类型3 ……对所有人说向所有在线用户发送消息(ⅴ)服务器端的断开连接事件中修改存储连接用户的元素个数的数组,卸载此控件,向所有在线用户发送消息离线。
③客户端(ⅰ)添加一个SOCKET套接字,窗体加载时使用UDP协议,发广播数据报;等待接收到服务器主机地址后使用TCP协议完成连接及数据传送。
(ⅱ)在客户端的数据到达事件中接受数据,如果客户端协议使用的是UDP协议,关闭客户端连接,重新设置客户端的协议、远程端口号、本地端口等参数,再调用连接方法请求连接,输入用户名,连接成功时发送用户名消息。
python基于tcp 协议实现智能聊天机器人的实验报告总结
python基于tcp 协议实现智能聊天机器人的实验报告总结Python是一种强大的编程语言,可以用于开发各种类型的应用程序。
最近,我利用Python基于TCP协议实现了一个智能聊天机器人的实验,并在此做一些总结。
首先,我使用Python的socket模块来建立TCP连接,这是实现基于TCP协议通信的基础。
通过socket模块,我可以轻松地建立客户端和服务器之间的连接,并实现数据的传输。
接着,我利用Python的多线程技术,将客户端和服务器端分别放在两个线程中运行。
这样可以实现客户端和服务器端的并发操作,提高了程序的效率和性能。
在实现智能聊天机器人的过程中,我利用了Python的第三方库NLTK (Natural Language Toolkit),这个库提供了很多自然语言处理的功能,包括分词、词性标注、句法分析等。
我利用NLTK中的一些功能,对用户输入的文本进行处理,从而实现了基本的对话功能。
另外,我还利用Python的机器学习库scikit-learn,训练了一个简单的分类模型,用来对用户输入的问题进行分类。
通过这个模型,我可以更准确地理解用户的意图,并给出更合理的回答。
在实验过程中,我遇到了一些问题,比如网络延迟、数据传输不稳定等。
为了解决这些问题,我采取了一些措施,比如增加缓冲区大小、优化网络传输算法等。
通过这些措施,我成功地解决了大部分网络相关的问题。
总的来说,我通过这个实验学到了很多关于Python编程和TCP通信的知识。
我发现Python是一种非常适合开发网络应用的语言,它的简洁性和灵活性使得开发过程变得更加高效。
通过这个实验,我对Python的理解更加深入,也对网络编程有了更深入的认识。
未来,我希望能够进一步完善这个智能聊天机器人,添加更多的功能和优化算法,使得它能够更好地满足用户的需求。
我相信,通过不断地学习和实践,我能够开发出更加智能和实用的应用程序,为人们的生活带来便利和乐趣。
网络聊天室实现报告
一、背景知识在传统生活里,人们利用写信、电话等方式联络,但此类方式周期缓慢,呆板且不可靠。
在这个信息极其发达的时代,随后我们可以用来进行信息交流的方法日益增多,比如电报、电话、电子邮件、OICQ等通讯手段,但是这些或者不方便或者有局限性或者有费用的问题。
近年来计算机技术的快速发展,特别是计算机网络的发展,越来越深刻的改变了人们生活的方方面面,使得人们能以更低廉的价格,开发出更方便、更实用的网络工具。
各种在线服务系统,更是深刻的影响了人们的联系和交流方式,使得人们可以在远隔千里之遥随时通讯。
过去的种种陈旧的联系方式,已经不能满足现代生活的需要。
网络聊天室凭借其友好的外观、强大的功能、使用的便利、联系的及时等特点博得现代人的青睐,其应用的市场十分广阔。
本系统使用的是C/S模式,使用C#进行聊天室的设计与开发。
本文主要介绍了所应用到的技术的基础知识,并探讨了建立聊天室的设计思想、方法与功能实现流程图。
本文所实现的聊天室具有良好的人机交互界面、合理的数据库结构可以实现发言、自动显示所在聊天室的成员等交互功能,经过测试调试,证明可实际应用。
下图为网络聊天室的主界面图1网络聊天室主运行界面图二、核心算法思想实现一个基于Socket的简易的聊天室,实现的思路如下:聊天室服务器端启动服务器时,将创建侦听套接字,创建用户列表,创建并启动侦听线程。
用户登录时,将创建套接字,与服务器直接连接,并创建客户端接收线程。
服务器端侦听到有用户上线后,将创建新的用户节点,并在主界面上显示用户上线,发送新的用户列表。
客户端发送信息时,将要发送的内容进行发送。
服务器端发送信息时,如果是发送给所有人,就遍历用户链表,如果是发送给某个用户,先在链表中找到该节点,再发送信息。
服务器端和客户端接收信息时,先读取聊天信息标识,做出判断后,依次读取信息,处理信息,并在主界面上显示,服务器端还要将准备好的信息发送给指定的用户。
开启客户端主界面后,就会启动文件接收侦听线程,如果有用户发送文件至此,将会有信息提示,确定接收后,将启动文件接收线程,对方用户端将启动文件发送线程。
基于tcp协议的网络聊天室
班级:软件113 姓名:蒋栋学号:1108050328 成绩:实验名称: 基于TCP的网络聊天室1.实验目的:掌握TCP通讯协议、掌握QTcpSocket2.实验内容:使用Qt的QtcpSocket实现简单的网络聊天程序,范例如图:包括拂去其程序和客户端程序,服务端程序可以创建一个聊天室,客户端程序可以输入登陆的用户名、服务器地址以及使用的端口号,然后进入聊天室,聊天室中的每一位用户均可以看见发布的信息。
3.实验方法:使用Qt的QtcpSocket,参考Qt网络编程实验。
4.实验过程tcpServer端代码:#include "dialog.h"#include "ui_dialog.h"Dialog::Dialog(QWidget *parent) :QDialog(parent),ui(new Ui::Dialog){ui->setupUi(this);ui->lineEdit->setText("8010");port=8010;}Dialog::~Dialog(){delete ui;}void Dialog::on_newchat_clicked(){server=new Server(this,port);connect(server,SIGNAL(updateServer(QString,int)),this,SLOT(updateServer(QString ,int)));ui->newchat->setEnabled(false);}void Dialog::updateServer(QString msg,int length){ui->listWidget->addItem (msg.left(length) );}tcpServer端server.cpp 代码:#include "server.h"#include <QTcpSocket>Server::Server(QObject*parent,int port):QTcpServer(parent){listen(QHostAddress::Any,port);}void Server::incomingConnection(int socketDescriptor){TcpclientSocket*tcpClientSocket=new TcpclientSocket(this);connect(tcpClientSocket,SIGNAL(updateClient(QString,int)),this,SLOT(updateClient (QString,int)));connect(tcpClientSocket,SIGNAL(disconnected(int)),this,SLOT(slotDisconnected(int )));tcpClientSocket->setSocketDescriptor(socketDescriptor);tcpClientSocketList.append(tcpClientSocket);}void Server::updateClient(QString msg, int length){emit updateServer(msg,length);for(int i=0;i<tcpClientSocketList.count();i++){QTcpSocket*item=tcpClientSocketList.at(i);if(item->write(msg.toLatin1(),length)!=length){continue ;};}}void Server::slotDisconnected(int descriptor){for(int i=0;i<tcpClientSocketList.count();i++){QTcpSocket*item=tcpClientSocketList.at(i);if(item->socketDescriptor()==descriptor){tcpClientSocketList.removeAt(i);return;}}return;}Tcpclient端代码:#include "dialog.h"#include "ui_dialog.h"#include <QMessageBox>Dialog::Dialog(QWidget *parent) :QDialog(parent),ui(new Ui::Dialog){ui->setupUi(this);ui->lineEdit_4->setText("8010");status=false;serverIP =new QHostAddress();port = 8010;ui->pb_send->setEnabled(false);}Dialog::~Dialog(){delete ui;}void Dialog::on_pb_send_clicked(){slotSend();}void Dialog::on_pb_enter_clicked(){slotEnter();}void Dialog::slotEnter(){if(!status){QString ip=ui->lineEdit_3->text();if(!serverIP->setAddress(ip)){QMessageBox::information(this,tr("error"),tr("server ip address error!"));return;}if(ui->LineEditUser->text()==""){QMessageBox::information(this,tr("error"),tr("User name error!"));return ;}userName=ui->LineEditUser->text();tcpSocket = new QTcpSocket(this);connect(tcpSocket,SIGNAL(connected()),this,SLOT(slotConnected())); connect(tcpSocket,SIGNAL(disconnected()),this,SLOT(slotDisconnected()));connect(tcpSocket, SIGNAL(readyRead()),this, SLOT(dataReceived()));tcpSocket->connectToHost ( *serverIP, port);status=true;}else{int length = 0;QString msg=userName+tr(":Leave Chat Room");if((length=tcpSocket->write(msg.toLatin1(),msg.length()))!=msg.length()){return ;}tcpSocket->disconnectFromHost();status=false;}}void Dialog::slotConnected(){int length = 0;ui->pb_send->setEnabled( true );ui->pb_enter->setText(tr("Leave"));QString msg=userName+tr(":Enter Chat Room");if((length=tcpSocket->write(msg.toLatin1(),msg.length()))!=msg.length()){return;}}void Dialog::slotDisconnected(){ui->pb_send->setEnabled( false );ui->pb_enter->setText(tr("Enter"));}void Dialog::slotSend(){if(ui->LineEditSend->text()==""){return ;}QString msg=userName+":"+ui->LineEditSend->text();tcpSocket->write(msg.toLatin1(),msg.length());ui->LineEditSend->clear();}void Dialog::dataReceived(){while (tcpSocket->bytesAvailable()>0){QByteArray datagram;datagram.resize(tcpSocket->bytesAvailable());tcpSocket->read(datagram.data(), datagram.size());QString msg=datagram.data();ui->listWidget->addItem (msg.left(datagram.size()));}}5.实验结果客户端1 服务器端客户端26.实验总结经过本次实验练习了TCP通讯协议、QTcpSocket 的使用。
网络编程基于TCP的简易聊天室实验报告
⽹络编程基于TCP的简易聊天室实验报告⽹络编程课程设计-基于TCP的简易聊天室⼀、实验基本信息概要1.题⽬要求熟悉异步⽹络编程的基本⽅法,掌握异步⽹络编程和⽹络协议设计的⽅法。
要求采⽤select 模型、WSAAsyncSelect模型、WSAEventSelect模型、重叠模型或完成端⼝等模型完成编程任务。
2.上机要求要求采⽤select模型、WSAAsyncSelect模型、WSAEventSelect模型、重叠模型或完成端⼝等模型完成下⾯的任务。
3.题⽬内容内容概要:实现⼀个聊天室,⽀持多⼈聊天。
也可以增加私聊等功能。
4.开发环境操作系统:Windows 7开发语⾔:C++集成开发环境:Microsoft Visual Studio 2010⼆、系统简介1.界⾯本软件使⽤DOS控制台界⾯,界⾯风格较为朴素,没⽤使⽤复杂的颜⾊。
但是对聊天时界⾯进⾏了⼀定的控制和修正使得界⾯较为美观,易读。
服务器:客户端:2.软件功能本软件实现了聊天室基本的功能,包括公开聊天,私聊,获取在线⽤户,更改昵称,获得帮助等。
1)公开聊天在光标处直接输⼊消息后按回车即为发送公开聊天,如下图所⽰。
2)私聊使⽤命令【/m 对⽅UID 消息】即可发送私聊,私聊只有对⽅可以看到,如下图所⽰:客户端1,密聊UID为132的⽤户。
发送后客户端2,UID为132的⽤户收到私聊消息。
3)获取在线⽤户列表使⽤命令【/list】即可获得在线⽤户列表,⽤户列表会议系统消息的⽅式返回,如下图所⽰。
命令发送后4)更改昵称使⽤命令【/name 你的新昵称】即可⽴即更改昵称,成功修改后服务器会以系统消息的⽅式返回成功修改的提⽰。
命令命令发送后5)帮助信息使⽤命令【/help】即可查看服务器的欢迎信息,⾥⾯包含了该聊天室的使⽤帮助,如下图所⽰。
命令命令发送后3.系统设计开发本软件时,我使⽤了⾯向对象的思想,把服务器和客户端封装成对应的类,类设计将会在下⼀节做详细介绍。
基于.TCP的简单一对一聊天程序设计
基于TCP的简单一对一聊天程序设计一、课程设计目的1、通过课程设计,使学生理论联系实际,在实践中进一步了解计算机网络体系构造,深入理解TCP/IP参考模型2、培养学生分析、解决问题的能力,提高学生动手能力。
3、使学生掌握搜集资料、调查研究、整理报告的方法。
4、初步掌握网络应用程序开发技术以及互联网的应用技术。
二、课程设计的要求及原理1、课程设计要求。
实现一个一对一的聊天程序。
其根本过程如下:效劳器首先启动,创立套节字等待客户连接;客户启动以后,创立套届字,然后和效劳器建立连接;连接建立以后,客户机和效劳器可以通过建立的套节字连接进展通信。
效劳器和客户端可以是一台电脑上的两个进程,也可以使分别部署在两台电脑上。
2、课程设计原理。
客户效劳器模型。
它是指客户/效劳器模型是所有网络应用的根底。
客户/效劳器分别指参与一次通信的两个应用实体,客户方主动地发起通信请求,效劳器方被动地等待通信的建立。
它是一个在建立分布式应用时最常用的范例。
在这种方案中客户应用程序向效劳器程序请求效劳。
这种方式隐含了在建立客户机/效劳器间通讯时的非对称性。
客户机/效劳器模型工作时要求有一套为客户机和效劳器所共识的惯例来保证效劳能够被提供〔或被承受〕。
这一套惯例包含了一套协议。
它必须在通讯的两头都被实现。
根据不同的实际情况,协议可能是对称的或是非对称的。
在对称的协议中,每一方都有可能扮演主从角色;在非对称协议中,一方被不可改变地认为是主机,而另一方那么是从机。
无论具体的协议是对称的或是非对称的,当效劳被提供时必然存在"客户进程"和"效劳进程"。
一个效劳程序通常在一个众所周知的地址监听对效劳的请求,也就是说,效劳进程一直处于休眠状态,直到一个客户对这个效劳的地址提出了连接请求。
在这个时刻,效劳程序被"惊醒"并且为客户提供效劳-对客户的请求作出适当的反响。
虽然基于连接的效劳是设计客户机/效劳器应用程序时的标准,但有些效劳也是可以通过数据报套接口提供的。
TCP实验报告
《—计算机网络—》TCP通信实验报告姓名:班级:学号:指导老师:浙江理工大学信息电子学院二○一四年十二月一、实验目的、利用c#编写异步tcp通讯程序,掌握socket语句的用法二、实验内容TCP实现一对一单人聊天,编程实现一个聊天室系统。
该系统首先必须设立服务器,建立完成后必须建立与服务器的连接。
建立成功后可以接收客户端输入的信息。
该系统包括客户端和服务器端两部分。
用户通过客户端发送消息。
服务器端在收到消息后,显示在主界面上实验报告要求有实现过程的流程图,对主要的函数及其参数给予说明,要有实现过程的主要程序段,并对各段程序的功能及作用进行说明三、实验代码1.server端using System;using System.Collections.Generic;using ponentModel;using System.Data;using System.Drawing;using System.Linq;using System.Text;using System.Threading.Tasks;using System.Windows.Forms;using ;using .Sockets;using System.IO;using System.Threading;namespace frmAsyncTcpServer{public partial class TCPServer : Form{// 申明变量private const int Port = 51388;private TcpListener tcpLister = null;private TcpClient tcpClient = null;IPAddress ipaddress;private NetworkStream networkStream = null;private BinaryReader reader;private BinaryWriter writer;// 申明委托// 显示消息private delegate void ShowMessage(string str);private ShowMessage showMessageCallback;// 显示状态private delegate void ShowStatus(string str);private ShowStatus showStatusCallBack;// 清空消息private delegate void ResetMessage();private ResetMessage resetMessageCallBack;public TCPServer(){InitializeComponent();// 显示消息showMessageCallback = new ShowMessage(showMessage);// 显示状态showStatusCallBack = new ShowStatus(showStatus);// 重置消息resetMessageCallBack = new ResetMessage(resetMessage); ipaddress = IPAddress.Loopback;tbxserverIp.Text = ipaddress.ToString();tbxPort.Text = Port.ToString();}// 显示消息private void showMessage(string str){lstbxMsgView.Items.Add(tcpClient.Client.RemoteEndPoint); lstbxMsgView.Items.Add(str);lstbxMsgView.TopIndex = lstbxMsgView.Items.Count - 1;}// 显示状态private void showStatus(string str){toolStripStatusInfo.Text = str;}// 清空消息private void resetMessage(){tbxMsg.Text = string.Empty;tbxMsg.Focus();}private void toolTip1_Popup(object sender, PopupEventArgs e){}private void TCPServer_Load(object sender, EventArgs e){}private void label1_Click(object sender, EventArgs e){}private void btnStart_Click(object sender, EventArgs e){tcpLister = new TcpListener(ipaddress, Port);tcpLister.Start();// 启动一个线程来接受请求Thread acceptThread = new Thread(acceptClientConnect);acceptThread.Start();}private void acceptClientConnect(){statusStripInfo.Invoke(showStatusCallBack, "正在监听");Thread.Sleep(1000);try{statusStripInfo.Invoke(showStatusCallBack, "等待连接");tcpClient = tcpLister.AcceptTcpClient();if (tcpLister != null){statusStripInfo.Invoke(showStatusCallBack, "接受到连接"); networkStream = tcpClient.GetStream();reader = new BinaryReader(networkStream);writer = new BinaryWriter(networkStream);}}catch{statusStripInfo.Invoke(showStatusCallBack, "停止监听");Thread.Sleep(1000);statusStripInfo.Invoke(showStatusCallBack, "就绪");}}private void btnStop_Click(object sender, EventArgs e){tcpLister.Stop();}private void btnClear_Click(object sender, EventArgs e){lstbxMsgView.Items.Clear();}private void btnReceive_Click(object sender, EventArgs e){statusStripInfo.Invoke(showStatusCallBack, "接受消息中");try{string receivemessage = reader.ReadString();lstbxMsgView.Invoke(showMessageCallback, receivemessage);StreamWriter wr = new StreamWriter(@"历史记录.txt", true,System.Text.Encoding.Default);for (int i = 0; i < lstbxMsgView.Items.Count; i++){wr.Write(lstbxMsgView.Items[i].ToString() + Environment.NewLine); }wr.Close();}catch{if (reader != null){reader.Close();}if (writer != null){writer.Close();}if (tcpClient != null){tcpClient.Close();}statusStripInfo.Invoke(showStatusCallBack, "断开了连接");// 重新开启一个线程等待新的连接Thread acceptThread = new Thread(acceptClientConnect);acceptThread.Start();}}private void btnSend_Click(object sender, EventArgs e){Thread sendThread = new Thread(SendMessage);sendThread.Start(tbxMsg.Text);}private void SendMessage(object state){statusStripInfo.Invoke(showStatusCallBack, "正在发送");try{writer.Write(state.ToString());Thread.Sleep(5000);writer.Flush();statusStripInfo.Invoke(showStatusCallBack, "完毕");tbxMsg.Invoke(resetMessageCallBack, null);lstbxMsgView.Invoke(showMessageCallback, state.ToString()); }catch{if (reader != null){reader.Close();}if (writer != null){writer.Close();}if (tcpClient != null){tcpClient.Close();}statusStripInfo.Invoke(showStatusCallBack, "断开了连接");// 重新开启一个线程等待新的连接Thread acceptThread = new Thread(acceptClientConnect);acceptThread.Start();}}private void button1_Click(object sender, EventArgs e){if (reader != null){reader.Close();}if (writer != null){writer.Close();}if (tcpClient != null){// 断开连接tcpClient.Close();}toolStripStatusInfo.Text = "断开连接";// 启动一个线程等待接受新的请求Thread acceptThread = new Thread(acceptClientConnect);acceptThread.Start();}private void button1_Click_1(object sender, EventArgs e){StreamReader file = new StreamReader(@"历史记录.txt", System.Text.Encoding.Default);string s = "";while (s != null){s = file.ReadLine();if (s != null && !s.Equals(""))lstbxMsgView.Items.Add(s);}file.Close();}}}2.client端using System;using System.Collections.Generic;using ponentModel;using System.Data;using System.Drawing;using System.Linq;using System.Text;using System.Threading.Tasks;using System.Windows.Forms;using ;using .Sockets;using System.Threading;using System.IO;namespace frmAsyncTcpClient{public partial class frmAsyncTcpClient : Form{// 申明变量private TcpClient tcpClient = null;private NetworkStream networkStream = null;private BinaryReader reader;private BinaryWriter writer;// 申明委托// 显示消息private delegate void ShowMessage(string str);private ShowMessage showMessageCallback;// 显示状态private delegate void ShowStatus(string str);private ShowStatus showStatusCallBack;// 清空消息private delegate void ResetMessage();private ResetMessage resetMessageCallBack;public frmAsyncTcpClient(){InitializeComponent();// 显示消息showMessageCallback = new ShowMessage(showMessage);// 显示状态showStatusCallBack = new ShowStatus(showStatus);// 重置消息resetMessageCallBack = new ResetMessage(resetMessage);}private void showMessage(string str){lstbxMsgView.Items.Add(tcpClient.Client.RemoteEndPoint); lstbxMsgView.Items.Add(str);lstbxMsgView.TopIndex = lstbxMsgView.Items.Count - 1;}private void showStatus(string str){toolStripStatusInfo.Text = str;}// 清空消息private void resetMessage(){tbxMsg.Text = "";tbxMsg.Focus();}private void toolStripLabel1_Click(object sender, EventArgs e) {}private void textBox5_TextChanged(object sender, EventArgs e) {}private void statusStrip1_ItemClicked(object sender, ToolStripItemClickedEventArgs e){}private void frmAsyncTcpClient_Load(object sender, EventArgs e){}private void tbxSendCount_TextChanged(object sender, EventArgs e){}private void label1_Click(object sender, EventArgs e){}private void lstbxMsgView_SelectedIndexChanged(object sender, EventArgs e) {}private void btnConnect_Click(object sender, EventArgs e){// 通过一个线程发起请求,多线程Thread connectThread = new Thread(ConnectToServer);connectThread.Start();}private void ConnectToServer(){try{// 调用委托statusStripInfo.Invoke(showStatusCallBack, "正在连接...");if (tbxSrvIp.Text == string.Empty || tbxPort.Text == string.Empty) {MessageBox.Show("请先输入服务器的IP地址和端口号");}IPAddress ipaddress = IPAddress.Parse(tbxSrvIp.Text);tcpClient = new TcpClient();tcpClient.Connect(ipaddress, int.Parse(tbxPort.Text));// 延时操作Thread.Sleep(1000);if (tcpClient != null){statusStripInfo.Invoke(showStatusCallBack, "连接成功");networkStream = tcpClient.GetStream();reader = new BinaryReader(networkStream);writer = new BinaryWriter(networkStream);}}catch{statusStripInfo.Invoke(showStatusCallBack, "连接失败");Thread.Sleep(1000);statusStripInfo.Invoke(showStatusCallBack, "就绪");}}private void btnReceive_Click(object sender, EventArgs e){Thread receiveThread = new Thread(receiveMessage);receiveThread.Start();}private void receiveMessage(){statusStripInfo.Invoke(showStatusCallBack, "接受中");try{string receivemessage = reader.ReadString();lstbxMsgView.Invoke(showMessageCallback, receivemessage);StreamWriter wr = new StreamWriter(@"历史记录.txt", true,System.Text.Encoding.Default);for (int i = 0; i < lstbxMsgView.Items.Count; i++){wr.Write(lstbxMsgView.Items[i].ToString() + Environment.NewLine); }wr.Close();}catch{if (reader != null){reader.Close();}if (writer != null){writer.Close();}if (tcpClient != null){tcpClient.Close();}statusStripInfo.Invoke(showStatusCallBack, "断开了连接"); }}private void btnDisconnect_Click(object sender, EventArgs e){if (reader != null){reader.Close();}if (writer != null){writer.Close();}if (tcpClient != null){// 断开连接tcpClient.Close();}toolStripStatusInfo.Text = "断开连接";}private void btnSend_Click(object sender, EventArgs e){Thread sendThread = new Thread(SendMessage);sendThread.Start(tbxMsg.Text);}private void SendMessage(object state){statusStripInfo.Invoke(showStatusCallBack, "正在发送...");try{writer.Write(state.ToString());Thread.Sleep(5000);writer.Flush();statusStripInfo.Invoke(showStatusCallBack, "完毕");tbxMsg.Invoke(resetMessageCallBack, null);lstbxMsgView.Invoke(showMessageCallback, state.ToString()); }catch{if (reader != null){reader.Close();}if (writer != null){writer.Close();}if (tcpClient != null){tcpClient.Close();}statusStripInfo.Invoke(showStatusCallBack, "断开了连接"); }}private void btnClear_Click(object sender, EventArgs e){lstbxMsgView.Items.Clear();}private void button1_Click(object sender, EventArgs e){StreamReader file = new StreamReader(@"历史记录.txt",System.Text.Encoding.Default);string s = "";while (s != null){s = file.ReadLine();if (s != null && !s.Equals(""))lstbxMsgView.Items.Add(s);}file.Close();}}}}四、实验结果五、实验心得通过本次实验,我掌握了异步TCP通信的性质,学会了建立C#窗体程序并用socket进行tcp通讯的编程。
聊天室——TCPIP原理及编程课程设计报告
《TCPIP原理及编程课程设计报告》课程设计报告书题目:局域网聊天室专业:网络工程班级:一班学生姓名:贺**学号: 2013**指导教师:李**完成日期: 2016年6月11日目录一、任务概述 (1)1.1设计目的 (1)1.2项目背景 (1)二、系统需求分析和概要设计 (1)2.1需求分析 (1)2.1.1服务器端工作流程 (1)2.1.2客户端工作流程 (1)2.2用例设计 (2)2.3整体框架设计 (5)2.4模块设计 (5)三、系统详细设计 (6)3.1服务器 (6)3.2客户端 (12)3.3主界面 (14)四、总结 (15)一、任务概述1.1设计目的本课题是建立聊天通信模型,设计一个聊天室软件,包括服务器端和客户端,通过选择类型决定是服务器还是客户端。
服务器端功能:初始化Socket,创建服务器端,向用户发出响应命令。
客户端功能:连接服务器,消息框中输入消息,当按下“发送消息”按钮时将信息发送给服务器。
通本课题的课程设计,可以比较深入的了解和掌握Winsock 控件基本属性、方法和事件,理解网络聊天通信的概念,使用传输控制协议(TCP)进行数据交流,初步掌握网络聊天通信程序的设计方法。
并能巩固和扩展大学期间的学习内容,进行项目的设计开发训练,更好的适应社会的需求。
1.2 项目背景聊天室程序一般都是以服务器提供服务端连接响应,使用者通过客户端程序连接到服务器,就可以与在同一服务器上的用户交谈,这是一个面向连接的通信过程。
因此,程序要在TCP/IP环境下,实现服务器端和客户端两部分程序。
二、系统需求分析和概要设计2.1需求分析2.1.1服务器端工作流程服务器端通过系统调用创建一个Socket数组后(即设定了接受连接客户的最大数目),与指定的本地端口绑定bind(),就可以在端口进行监听listen。
如果有客户端连接请求,则在数组中选择一个空Socket,将客户端地址赋给这个Socket。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
网络编程课程设计-基于TCP的简易聊天室一、实验基本信息概要1.题目要求熟悉异步网络编程的基本方法,掌握异步网络编程和网络协议设计的方法。
要求采用select 模型、WSAAsyncSelect模型、WSAEventSelect模型、重叠模型或完成端口等模型完成编程任务。
2.上机要求要求采用select模型、WSAAsyncSelect模型、WSAEventSelect模型、重叠模型或完成端口等模型完成下面的任务。
3.题目内容内容概要:实现一个聊天室,支持多人聊天。
也可以增加私聊等功能。
4.开发环境操作系统:Windows 7开发语言:C++集成开发环境:Microsoft Visual Studio 2010二、系统简介1.界面本软件使用DOS控制台界面,界面风格较为朴素,没用使用复杂的颜色。
但是对聊天时界面进行了一定的控制和修正使得界面较为美观,易读。
服务器:客户端:2.软件功能本软件实现了聊天室基本的功能,包括公开聊天,私聊,获取在线用户,更改昵称,获得帮助等。
1)公开聊天在光标处直接输入消息后按回车即为发送公开聊天,如下图所示。
2)私聊使用命令【/m 对方UID 消息】即可发送私聊,私聊只有对方可以看到,如下图所示:客户端1,密聊UID为132的用户。
发送后客户端2,UID为132的用户收到私聊消息。
3)获取在线用户列表使用命令【/list】即可获得在线用户列表,用户列表会议系统消息的方式返回,如下图所示。
命令发送后4)更改昵称使用命令【/name 你的新昵称】即可立即更改昵称,成功修改后服务器会以系统消息的方式返回成功修改的提示。
命令命令发送后5)帮助信息使用命令【/help】即可查看服务器的欢迎信息,里面包含了该聊天室的使用帮助,如下图所示。
命令命令发送后3.系统设计开发本软件时,我使用了面向对象的思想,把服务器和客户端封装成对应的类,类设计将会在下一节做详细介绍。
通行方面我在服务器接受客户端消息,和客户端接受服务器消息时使用了select模型,发送信息我使用的是普通的socket原语。
基本原理为服务器与客户端建立TCP连接,然后服务器负责路由消息到各个客户端。
4.优点与缺点本软件对流程复杂的SELECT模型进行了细致的拆分与抽象,做到了逻辑流程清晰,每个函数简洁易懂,层次分明。
例如服务器启动函数:它其实就完成了一个简单的流程,初始化socket,绑定,监听,初始化fd_socket集合,死循环调用select。
通过合理的封装底层原语和加入异常处理(异常交给顶层处理),使得代码专注于业务流程而不是繁杂的异常判断语句,在看下面这个函数DoSelect()。
它也只完成一个简单的流程,调用select,然后循环处理有读事件的socket。
接下来的DoFDRead()函数完成的事情也非常直接,如果有事件的socket是监听socket的话,那么就是接收到了一个新的连接,否则是接收到了新的小。
从上面这个简单的例子中可以看到,本软件最大的优点就是精心设计的类和函数。
避免了使用select模型常见的反复嵌套的循环和判断,每个函数清晰明了。
本系统还存在以下不足,首先是没有对界面做更深入的优化,只是做了最基本的调整,让输入输出更加雅观,其次是底层原语的封装并没有考虑到泛用性。
三、系统详细设计这部分的文档在编码之前已经基本完成,由于时间较为仓促,部分内容可能和实际有所出入。
1.ChatServer类该类负责完成服务器所有操作。
1)类图2) 成员变量Map<SOCKET, string> m_clients 聊天者的SOCKET与昵称的映射fd_set m_fdSocket 可用套接字集合fd_set m_fdRead 有事件发生的套接字集合SOCKET m_sListen 监听SocketSOCKET m_sNowClient 当前处理的客户套接字int m_nPort 监听端口3) 方法设计void Bind()void Listen()void Select()int Recv()SOCKET Accept()封装底层原语,并加入异常机制,使得外部调用简约明了。
构造函数传入监听端口,初始化m_nPortStart()1)初始化监听套接字:void InitListenSocket()2)绑定套接字至本地机器:void Bind()3)进入监听模式(设置为非阻塞):void Listen()4)初始化可用套接字集合void InitFDSocket()5)死循环,调用select方法DoSelect()6)结束DoSelect()1)令m_fdRead = m_fdSocket2)调用Select()3)循环处理Select的结果DoFdRead(Socket sRead)4)结束DoFdRead(int iReadIndex)1)判断是否为m_sListen2)是m_sListen RecvNewConnect()3)否则令m_sNowClient = m_fdRead[iReadIndex],调用RecvNewMessage() RecvNewConnect()1)判断是否达到套接字上线2)调用Accept(),接收连接sClient3)添加sCilent 至m_fdSocket4)添加套接字至m_clients AddClientToInfoMap(string name) AddClientToInfoMap(string name)1)以SOKCET为键,name为值加入MAPRecvNewMessage()1)调用Recv函数2)是否为命令IsCommand(string str)3)是,则DoCommand(string cmd)4)否,则DoMessage(string msg)5)结束IsCommand(string str)1)判断是否以"/" 开头DoCommand(string cmd)1)判断指令,并解析命令与参数(argc, argv)2)调用指令处理函数3)假设只有SetName命令,那么则将对应的套接字的名称设置DoMessage(string msg)1)拼接消息与名字BuildMsg(string msg)2)在服务器上输出3)消息路由DispatchMessage(string msg)BuildMsg(string msg)1)从m_clients 中取出用户昵称2)拼接字符串,形成格式如下超人君(127.0.0.1) 23:49:48 说:大家好!即为:昵称(IP地址)时间说:消息正文3)返回DispatchMessage(string msg)1)构造迭代器2)遍历m_clients,若不是自身,则派送消息Send() 2.ChatClient 类该类负责处理客户端的所有操作。
1)类图2)字段设计SOCKET m_sClient 客户端自身的socketSOCKET m_sServer 服务器socketstring m_name 昵称sockaddr_in m_ServerAddr; 服务器地址3)方法设计构造函数根据端口号和服务器IP初始化m_serverConnect()void Select()int Recv()void Send()int Select()封装底层原语,加入异常处理,使得外部调用节约优雅。
void Start()1)初始化套接字InitClientSocket()2)连接服务器Connect() 设置为非阻塞模式3)获取名字并发送至服务器InitName()4)创建新线程并显示替他用户发言线程函数RecvMsgThread() 5)循环SendMsg()6)关闭客户端CloseClient()InitName()1)提示输入昵称2)获取昵称3)合法性判断判断重复4)添加命令格式5)发送至服务器SendMsg()1)读取一行消息2)判断是否为命令IsCommand(string str)3)命令:处理命令DoCommand(string cmd)4)消息:处理消息DoMessage(string msg)DoMessage(string msg)1)发送消息Send()2)本地回显RecvMsgThread()1)初始化fdSocket,将m_sClient加入2)创建fdRead3)死循环,将m_sClient拷贝至fdRead4)调用Select5)循环,并输出收到的消息Recv()3.SocketException类该类负责记录SOKCET错误的代码以及错误信息。
1)类图4.命令协议命令格式为/命令参数1 参数21. 退出: /exit2. 获取在线用户列表:/getuser3. 私聊:/m UID 信息4. 清屏:/clear5. 帮助:/help处理方式IsCommand(string str) 负责解析是否为命令判断首字母是否为斜杠"/" str.at(0) == '/'ResoveCommand(string cmd, int& argc, string argv[]) 若是命令将命令解析为argc,argv DoCommand(string cmd) 处理命令,调用具体的XXX命令处理函数DoCmdXXXX()。
5.消息格式1)公共消息超人君(127.0.0.1) UID:100 说:大家好!李四(127.0.0.1) UID:101 说:你好!!2)私聊你悄悄地对ABC UID:100 说:你好CDF UID:101 悄悄地对你说:你好3)服务器消息【系统消息】XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX。
4)程序内部提示[System Info]xxxxxxxxxxxxxxxxxxxxxxxxx四、系统测试1. 服务器使用错误2. 客户端使用错误3. 启动服务器5.启动客户端客户端出现欢迎信息以及昵称输入提示。
服务器出现连接提示6.关闭客户端服务器出现断开连接提示7.启动服务器错误提示给出错误提示信息和提示代码8.公开聊天所有客户端以及服务器都会显示。
9.私聊只有私聊的二人才能看到聊天信息,其他用户和服务器无法看到。
10.错误的私聊私聊自己会得到一个错误提示私聊不存在的用户也会得到一个错误提示11.更名12.获取在线用户13.帮助14.非法指令非法指令会给出错误提示。
15.非法的指令参数16.连接服务器失败五、心得体会这次实现我深入研究了select模型的使用,完成了一个简易的聊天室。
这次试验也使我在编程技巧方面也有了很大的提高。
六、完整代码Charserverd.cpp 服务器main函数文件#include "ChatServer.h"#include "SockException.h"#include "InitSock.h"#include <iostream>using namespace std;InitSock initSock;int main(int argc, char* argv[]){if (argc < 2){cout << "Usage:" << argv[0] << " Port " << endl;return 1;}ChatServer charServer(atoi(argv[1]));try{charServer.Start();}catch (SockException& e){cout << e.GetErrorInfo() << endl;cout << "[System Error]Error Code:" << e.GetErrorCode() << endl;}}ChatServer.h 服务器类头文件#ifndef CHAT_SERVER_H#define CHAT_SERVER_H#include <WinSock2.h>#include <string>#include <map>#include "ClientInfo.h"using namespace std;class ChatServer{public:void Start();void End();ChatServer(int nPort);~ChatServer(void);private:void InitFDSocket();void DoSelect();void DoFDRead(SOCKET sRead);void RecvNewConnect();string IPAddrToString(sockaddr_in sin);void AddClientToInfoMap(ClientInfo info);void RecvNewMessage();bool IsCommand(string str);void DoCommand(string cmd);void ResoveCommand(string cmd, int& argc, string argv[]);void DoCmdName(int argc, string argv[]);void DoCmdGetUsers(int argc, string argv[]);void DoMessage(string msg);void DoCmdPrivateMsg(int argc, string argv[]);string BuildMessage(string str, bool bIsPublic);string BuildSystemMsg(string str);void DispatchMessage(string msg);void CloseConnect();string IntToString(int nNum);//============简单封装底层原语=============void InitListenSocket();void Bind();void Listen() ;int Select();int Recv(char msgBuff[]);void Send(string msg, SOCKET client);SOCKET Accept(sockaddr_in& sin);//==========================================private:map<SOCKET, ClientInfo> m_clients;fd_set m_fdSocket;fd_set m_fdRead;SOCKET m_sListen;SOCKET m_sNowClient;int m_nPort;};#endif CHAT_SERVER_HChatServer.cpp 服务器类#include <WinSock2.h>#include <iostream>#include "ChatServer.h"#include "SockException.h"#pragma comment(lib, "ws2_32.lib")using namespace std;#define MAX_BUFF_SIZE 500typedef map<SOCKET, ClientInfo>::iterator map_it;ChatServer::ChatServer(int nPort){this->m_nPort = nPort;}void ChatServer::Start(){InitListenSocket();Bind();Listen();InitFDSocket();while (true){DoSelect();}}void ChatServer::DoSelect(){m_fdRead = m_fdSocket;int nRet = Select();if (nRet > 0){for (int i = 0; i < m_fdRead.fd_count; i++){DoFDRead(m_fdRead.fd_array[i]);}}}void ChatServer::DoFDRead(SOCKET sRead){if (sRead == m_sListen){RecvNewConnect();}else{m_sNowClient = sRead;RecvNewMessage();}}void ChatServer::RecvNewConnect(){if (m_fdSocket.fd_count >= FD_SETSIZE){cout << "[System Info]接受连接达到上限,拒绝连接"<< endl;return;}sockaddr_in clientAddr;m_sNowClient = Accept(clientAddr);ClientInfo clientInfo(clientAddr);cout << "[System Info]接受来自"<< clientInfo.GetIp() << "的连接" << endl;FD_SET(m_sNowClient, &m_fdSocket);AddClientToInfoMap(clientInfo);}string ChatServer::IPAddrToString(sockaddr_in sin){string str = inet_ntoa(sin.sin_addr);str.append(":");char szFormat[20];str.append(ltoa( ntohs(sin.sin_port),szFormat,10));return str;}void ChatServer::AddClientToInfoMap(ClientInfo info){m_clients[m_sNowClient] = info;}void ChatServer::RecvNewMessage(){char msgBuff[MAX_BUFF_SIZE];int nRet = Recv(msgBuff);string msg(msgBuff);if (nRet <= 0) return;if (IsCommand(msg)){DoCommand(msg);}else{DoMessage(msg);}}void ChatServer::DoCommand(string cmd){string argv[100];ResoveCommand(cmd, argc, argv);if (argv[0] == "name"){DoCmdName(argc, argv);}else if (argv[0] == "list"){DoCmdGetUsers(argc, argv);}else if(argv[0] == "m"){DoCmdPrivateMsg(argc, argv);}else{Send("【系统消息】命令不存在,请使用/help 命令查看命令帮助", m_sNowClient);}}void ChatServer::ResoveCommand(string cmd, int& argc, string argv[]){int count = 0;for(int i = 1; i < cmd.size(); i++){char c = cmd.at(i);if (c != ' '){argv[count] += c;}else{count ++;}}argc = ++count;}void ChatServer::DoCmdGetUsers(int argc, string argv[]){if (argc != 1){return;}string online = IntToString(m_clients.size());msg.append("【系统消息】在线人数共" + online + "人:");msg.append( "\n\r");map_it begin = m_clients.begin();map_it end = m_clients.end();for (; begin != end; ++begin){msg.append("\t" + begin->second.GetName() + " " + begin->second.GetIp());msg.append(" UID:" + IntToString((int)begin->first));msg.append("\n\r");}Send(msg, m_sNowClient);}void ChatServer::DoCmdName(int argc, string argv[]){if (argc != 2){Send("【系统消息】命令格式错误USAGE: /name 你的昵称", m_sNowClient);return;}string name = argv[1];m_clients[m_sNowClient].SetName(name);Send("【系统消息】昵称已修改为:" + name, m_sNowClient);}void ChatServer::DoMessage(string str){string msg = BuildMessage(str, true);cout << msg << endl;DispatchMessage(msg);}/*string ChatServer::BuildMssage(string str){ClientInfo info = m_clients[m_sNowClient];string name = info.GetName();string ip = info.GetIp();string msg = name;if (name != ip){msg.append("(" + ip + ")");char buff[10];string id(itoa((int)m_sNowClient, buff, 10));msg.append(" UID:" + id);msg.append(" 说:");msg.append("\n\r ");msg.append(str);return msg;}*/string ChatServer::BuildSystemMsg(string str){string msg("【系统消息】");msg.append(str);return msg;}string ChatServer::BuildMessage(string str, bool bIsPublic){ClientInfo info = m_clients[m_sNowClient];string name = info.GetName();string ip = info.GetIp();string uid = IntToString((int)m_sNowClient);string msg(name);if (ip != name && bIsPublic == true){msg.append("(" + ip + ")");}msg.append(" ");msg.append("UID:" + uid);msg.append(" ");bIsPublic ? msg.append("说:") : msg.append("悄悄地对你说:");msg.append("\n\r");msg.append(" ");msg.append(str);return msg;}void ChatServer::DoCmdPrivateMsg(int argc, string argv[]){if (argc < 3){Send("【系统消息】命令格式错误USAGE: /m 目标UID 私聊内容", m_sNowClient);return;}SOCKET s = (SOCKET)atoi(argv[1].c_str());map_it it = m_clients.find(s);if (it == m_clients.end()){Send("【系统消息】该用户不存在", m_sNowClient);return;}if (it->first == m_sNowClient){Send("【系统消息】您不能和自己私聊", m_sNowClient);return;}string name = it->second.GetName();string uid = IntToString(s);string toDest = BuildMessage("", false);string toSrc = string("你悄悄地对" + name + " UID:" + uid + " 说:\n\r ");string other;for (int i = 2; i < argc; i++){other.append(argv[i]);other.append(" ");}Send(toDest + other, s);Send(toSrc + other, m_sNowClient);}void ChatServer::DispatchMessage(string msg){map_it begin = m_clients.begin();map_it end = m_clients.end();for (; begin != end; ++begin){Send(msg, begin->first);}}bool ChatServer::IsCommand(string str){if (str.at(0) == '/'){return true;}else{return false;}}void ChatServer::CloseConnect(){cout << "[System Info]来自" << m_clients[m_sNowClient].GetIp() << "的连接已断开" << endl;closesocket(m_sNowClient);FD_CLR(m_sNowClient,&m_fdSocket);}void ChatServer::InitFDSocket(){FD_ZERO(&m_fdSocket);FD_SET(m_sListen, &m_fdSocket);}void ChatServer::InitListenSocket(){m_sListen = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);if (m_sListen == INVALID_SOCKET){throw SockException("[System Error]创建套接字失败:");}}void ChatServer::Bind(){sockaddr_in sin;sin.sin_family = AF_INET;sin.sin_addr.S_un.S_addr = INADDR_ANY;sin.sin_port = htons(m_nPort);if (bind(m_sListen, (sockaddr*)&sin, sizeof(sin) )== SOCKET_ERROR){throw SockException("[System Error]无法绑定端口");}else{cout << "[System Info]成功绑定端口:" << m_nPort << endl;}}void ChatServer::Listen(){if (listen(m_sListen, 10) == SOCKET_ERROR){throw SockException("[System Error]服务器监听端口失败");}else{cout << "[System Info]服务器在" << m_nPort << "端口开始监听" << endl;}u_long value = 1;if (ioctlsocket(m_sListen, FIONBIO, &value)){throw SockException("[System Error]设置服务器为非阻塞模式失败");}}int ChatServer::Select(){int nRet = select(0, &m_fdRead, NULL, NULL, NULL);if (nRet == SOCKET_ERROR){throw SockException("[System Error]调用SELECT原语失败");}else{return nRet;}}SOCKET ChatServer::Accept(sockaddr_in& sin){int nLen = sizeof(sin);SOCKET sNew = accept(m_sListen, (sockaddr*)&sin, &nLen);if (sNew == INVALID_SOCKET){throw SockException("[System Error]调用ACCEPT原语接受连接失败");}return sNew;}int ChatServer::Recv(char msgBuff[]){int nRet = recv(m_sNowClient, msgBuff, MAX_BUFF_SIZE, 0);if (nRet == SOCKET_ERROR){CloseConnect();return 0;}else{msgBuff[nRet] = '\0';return nRet;}}void ChatServer::Send(string msg, SOCKET client){if (send(client, msg.c_str(), msg.size(), 0) == SOCKET_ERROR){string errorIp = m_clients[client].GetIp();throw SockException("[System Error]发送信息" + msg + "至" + errorIp + "失败");}}string ChatServer::IntToString(int nNum){char buff[10];string str(itoa(nNum, buff, 10));return str;}ChatServer::~ChatServer(void){}ClientInfo.h 客户信息类#include <string>using namespace std;class ClientInfo{public:ClientInfo(){}ClientInfo(string ip, int port, string name){this->ip = ip;this->port = port;this->name = name;}ClientInfo(sockaddr_in sin){ip = inet_ntoa(sin.sin_addr);//port = ntohs(sin.sin_port);name = ip;//name.append(":");//char szFormat[20];//name.append(ltoa( ntohs(sin.sin_port),szFormat,10));}string GetIp(){return ip;}string GetName(){return name;}int GetPort(){return port;}void SetName(string name){this->name = name;}private:string name;string ip;int port;};Charclientd.cpp 客户端main函数#include "SockException.h"#include "InitSock.h"#include <iostream>#include "ChatClient.h"using namespace std;InitSock initSock;int main(int argc, char* argv[]){try{if (argc < 3){cout << "Usage:" << argv[0] << " Ip Port " << endl;return 1;}ChatClient client(argv[1],atoi(argv[2]));client.Start();}catch (SockException& e){cout << e.GetErrorInfo() << endl;cout << "[System Error]Error Code:" << e.GetErrorCode() << endl;}}ChatClient.h 客户端头文件#ifndef CHAT_CLIENT_H#define CHAT_CLIENT_H#include <string>#include <WinSock2.h>using namespace std;class ChatClient{public:ChatClient(string addr, int nPort);~ChatClient(void);void Start();void End();SOCKET GetClientSock();private:void Connect();int Recv();void Send(string msg);int Select();void InitClientSocket();string IPAddrToString(sockaddr_in sin);void Welcome();void SendMsg();void InitName();bool IsCommand(string str);void DoMessage(string msg);void DoCommand(string cmd);void ResoveCommand(string cmd, int& argc, string argv[]);string GetLine();private:string m_name;SOCKET m_sClient;SOCKET m_sServer;sockaddr_in m_serverAddr;};#endif CHAT_CLIENT_HChatClient.cpp 客户端类#include <WinSock2.h>#include <iostream>#include <process.h>#include <Windows.h>#include "ChatClient.h"#include "SockException.h"#pragma comment(lib, "ws2_32.lib")#define MAX_BUFF_SIZE 500using namespace std;void RecvMsgThread(void * param);ChatClient::ChatClient(string addr, int nPort)m_serverAddr.sin_addr.S_un.S_addr = inet_addr(addr.c_str());m_serverAddr.sin_port = htons(nPort);m_serverAddr.sin_family = AF_INET;}ChatClient::~ChatClient(void){}void ChatClient::Start(){InitClientSocket();Connect();Welcome();Sleep(1000);InitName();_beginthread(RecvMsgThread,NULL,(void*)this);while (true){SendMsg();}}void ChatClient::Welcome(){cout << "=============================================================" << endl;cout << " ******欢迎使用简易聊天室****** " << endl;cout << "操作指南:1)在控制台中直接输入后,按回车即可发送公共聊天消息" << endl;cout << " 2)以斜杠(/)开头的消息将会当做命令处理" << endl;cout << " " << endl;cout << "命令指南:1)退出USAGE: /exit " << endl;cout << " 2)获取在线用户USAGE: /list " << endl;cout << " 3)更改昵称USAGE: /name 你的昵称" << endl;cout << " 4)私聊USAGE: /m 对方UID 消息" << endl;cout << " 5)帮助信息USAGE: /help " << endl;cout << "=============================================================" << endl;}void ChatClient::InitName()string name;cout << "请输入昵称:";name = GetLine();Send("/name " + name);}void ChatClient::SendMsg(){string msg;msg = GetLine();if (msg == ""){return;}if (IsCommand(msg)){DoCommand(msg);}else{DoMessage(msg);}}string ChatClient::GetLine(){string input;getline(cin, input);HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);CONSOLE_SCREEN_BUFFER_INFO bInfo;GetConsoleScreenBufferInfo(hOut, &bInfo);COORD pos;pos.X = bInfo.dwCursorPosition.X;pos.Y = bInfo.dwCursorPosition.Y - 1;FillConsoleOutputCharacter(hOut, ' ', input.size(), pos, NULL);SetConsoleCursorPosition(hOut, pos);return input;}void ChatClient::DoCommand(string cmd){int argc;string argv[100];ResoveCommand(cmd, argc, argv);if (argv[0] == "exit"){//system("exit");}else if (argv[0] == "help"){Welcome();}else{DoMessage(cmd);}}void ChatClient::DoMessage(string msg){//TODOSend(msg);}void ChatClient::ResoveCommand(string cmd, int& argc, string argv[]) {int count = 0;for(int i = 1; i < cmd.size(); i++){char c = cmd.at(i);if (c != ' '){argv[count] += c;}else{count ++;}}argc = ++count;}bool ChatClient::IsCommand(string str)if (str.at(0) == '/'){return true;}else{return false;}}void ChatClient::InitClientSocket(){m_sClient = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);if (m_sClient == INVALID_SOCKET){throw SockException("[System Error]创建套接字失败");}}void ChatClient::Connect(){if (connect(m_sClient, (sockaddr*)&m_serverAddr, sizeof(m_serverAddr)) == SOCKET_ERROR){throw SockException("[System Error]连接服务器:" + IPAddrToString(m_serverAddr) + "失败");}else{cout << "[System Info]连接服务器" + IPAddrToString(m_serverAddr) + "成功" << endl;}}void ChatClient::Send(string msg){if (send(m_sClient, msg.c_str(), msg.size(), 0) == SOCKET_ERROR){throw SockException("[System Error]发送消息:" + msg + "失败");}}string ChatClient::IPAddrToString(sockaddr_in sin){string str = inet_ntoa(sin.sin_addr);str.append(":");char szFormat[20];str.append(ltoa( ntohs(sin.sin_port),szFormat,10));return str;}void RecvMsgThread(void * param){ChatClient *cp = (ChatClient*)param;fd_set fdSocket;FD_ZERO(&fdSocket);FD_SET(cp->GetClientSock(), &fdSocket);fd_set fdRead;char msgBuff[MAX_BUFF_SIZE];while (true){fdRead = fdSocket;if (select(0,&fdRead,NULL,NULL,NULL)>0){for (int i = 0; i< fdRead.fd_count; i++){int nRet = recv(fdRead.fd_array[i], msgBuff,MAX_BUFF_SIZE,0);if ( nRet > 0){msgBuff[nRet] = '\0';cout << msgBuff << endl;}}}}}SOCKET ChatClient::GetClientSock(){return m_sClient;}InitSock.cpp 初始化WINSOCK类#ifndef INITSOCK_H#define INITSOCK_H#include <winsock2.h>#pragma comment(lib, "WS2_32")class InitSock{public:InitSock(BYTE minorVer = 2, BYTE majorVer = 2){WSADATA wsaData;WORD sockVersion = MAKEWORD(minorVer, majorVer);if(WSAStartup(sockVersion, &wsaData) != 0){exit(0);}}~InitSock(){WSACleanup();}};#endif INITSOCK_HSockException.h 异常类#ifndef SOCK_EXCEPTION_H#define SOCK_EXCEPTION_H#include <string>#include <WinSock2.h>using namespace std;class SockException{public:string GetErrorInfo(){return m_strErrorInfo;}int GetErrorCode(){return m_nErrorCode;}void SetErrorCode(string strErrorCode);void SetErrorInfo(string strErrorInfo);SockException() {}SockException(int nErrorCode, string strErrorInfo){m_nErrorCode = nErrorCode;m_strErrorInfo = strErrorInfo;}SockException(string strErrorInfo){int nErrorCode = WSAGetLastError();m_nErrorCode = nErrorCode;m_strErrorInfo = strErrorInfo;}private:int m_nErrorCode;string m_strErrorInfo;};#endif SOCK_EXCEPTION_H。