实现一个一对多的聊天程序

发布时间:2012-10-23 14:51:13   来源:文档文库   
字号:

实现一个一对多的聊天程序

一、实验题目

实现一个一对多的聊天程序。其基本过程如下:服务器首先启动,创建套接字后等待客户的连接;客户启动以后,创建套接字,然后和服务器建立连接;连接建立后,客户机和服务器可以通过建立的套接字连接进行通信。服务器和客户端可以是一台电脑上的两个进程,也可以分别部署在两台电脑上。

二、原理概述

TCP是一种可靠的、基于连接的网络传输协议,当两个网络进程准备进行通信时,都必须首先建立各自的一个套接口,其中服务器建立套接口后,侦听来自网络的客户连接请求,客户通过套接口,指定服务器的IP 地址和端口号,便可与服务器通信。

聊天程序采用的是C/S通信模式,即客户/服务模式,它把一个应用划分成功能不同的两个部分,分别在不同的计算机上运行,其中一个为服务端程序,用来响应和提供固定的服务,一个为客户端程序,用来向服务端提出请求和要求某种服务。在数量关系上,通常有一对多的(即一个服务端程序和一个客户端程序之间通信)。

客户机/服务器模式在操作过程中采取的是主动请示方式:

首先服务器方要先启动,并根据请示提供相应服务:

1)打开一通信通道并告知本地主机,它愿意在某一个公认地址上接收客户请求。

2)等待客户请求到达该端口。

3)接收到重复服务请求,处理该请求并发送应答信号。

4)返回第二步,等待另一客户请求

5)关闭服务器。

客户方:

1)打开一通信通道,并连接到服务器所在主机的特定端口。

2)向服务器发送服务请求报文,等待并接收应答;继续提出请求……

3)请求结束后关闭通信通道并终止。

1基于连接的服务者、客户服务流程图

三、设计方案

服务程序运行在服务器主机的某个端口上,一旦启动服务,它将在这个端口上倾听,等待客户程序发来的请求。服务器的套接口用服务器套接口类(ServerSocket)来建立。

1、根据程序设计题目时首先明确程序的目的以及任务

2、利用JAVA语言编写程序,使用套接字来完成测试功能。

3、程序在Eclipcse环境中编译,根据错误提示查找分析并修改原程序

四、程序编写:

import java.io.BufferedReader;

import java.io.BufferedWriter;

import java.io.IOException;

import java.io.InputStreamReader;

import java.io.OutputStreamWriter;

import java.net.ServerSocket;

import java.net.Socket;

import java.text.SimpleDateFormat;

import java.util.List;

import java.util.List;

/** 

 * @Title 服务器

 * @author Allen

 * @version 2010-5-3 下午08:28:36

 */

public class Server {

ServerSocket server = null;

List clients = new List();

SimpleDateFormat sdf = new SimpleDateFormat("MM-dd HH:mm:ss");

public void begin(){

//读取客户端的userName

BufferedReader bufUserName = null;

boolean started = false;

String userName = null;

try {

server = new ServerSocket(8888);

System.out.println("服务器启动成功!  端口" + server.getLocalPort() + "监听中...");

started = true;

while(started){

Socket socket = server.accept();

bufUserName = new BufferedReader(new InputStreamReader(socket.getInputStream()));

userName = bufUserName.readLine();

System.out.println("用户:" + userName + "  IP: " + socket.getLocalSocketAddress() + "   client connect...");

//bufUserName.close();

SC sc = new SC(socket);

new Thread(sc).start();

clients.add(sc);

}

} catch (IOException e) {

System.out.println("端口启动失败..." + e.getMessage() + "\n 程序安全退出...");

System.exit(0);

}

} 

public static void main(String[] args) {

new Server().begin();

}

private class SC implements Runnable{ 

BufferedReader br = null;

BufferedWriter bw = null;

Socket socket = null;

boolean isConnect = false;

public SC(Socket socket){

this.socket = socket;

try {

br = new BufferedReader(new InputStreamReader(socket.getInputStream()));

bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));

isConnect = true;

} catch (IOException e) {

e.printStackTrace();

}

}

public void sendMessage(String str){

try {

//bw.write(str + sdf.format(new Date()) + "\n");

bw.write(str);

bw.newLine();

bw.flush();

} catch (IOException e) {

e.printStackTrace();

}

}

public void run() {

try{

String strRead = null;

while(isConnect){

while((strRead = br.readLine()) != null){

System.out.println("Server readLine..." + strRead);

for(int i = 0; i < clients.size(); i++){

clients.get(i).sendMessage(strRead);

}

}

}

}catch(Exception e){

try {

br.close();

socket.close();

} catch (IOException e1) {

e1.printStackTrace();

}

e.getStackTrace();

}finally{

try {

if(br != null) br.close();

if(bw != null) bw.close();

if(socket != null)  {

socket.close();

//s = null;

}

} catch (IOException e1) {

e1.printStackTrace();

}

}

}

}

}

import java.awt.*;

import java.awt.event.*;

import java.io.*;

import java.net.Socket;

import java.net.UnknownHostException;

import java.text.SimpleDateFormat;

import java.util.Date;

import javax.swing.*;

/** 

 * @Title  客户端

 * @author Allen

 * @version 2010-5-3 下午08:28:47

 */

public class Client extends JFrame {

Socket socket = null;

JTextField jname = null; 

JTextField text = new JTextField();

JTextArea area = new JTextArea(10, 40);

BufferedReader br = null;

BufferedWriter bw = null;

BufferedWriter name_buf = null;

boolean connected = false;

SimpleDateFormat sdf = new SimpleDateFormat("MM-dd HH:mm:ss");

static String userName = null;

public Client(){

initFrame();

}

public static void main(String[] args) {

new Client();

}

public String getUserName(){

return userName;

}

public void initFrame(){

//setTitle(userName);

setSize(400, 300);

setLocation(500, 200);

this.setResizable(false);

JPanel panel = new JPanel();

GridBagConstraints gbc = new GridBagConstraints();

//GridBagLayout layout = new GridBagLayout();

FlowLayout layout = (FlowLayout)panel.getLayout();

layout.setAlignment(FlowLayout.RIGHT);

gbc.anchor = GridBagConstraints.LINE_END;

JButton btn_send = new JButton("send");

JButton btn_clear = new JButton("clear");

panel.setLayout(layout);

panel.add(btn_clear);

panel.add(btn_send, gbc);

area.setLineWrap(true);

area.setEditable(false);

JScrollPane jsp = new JScrollPane(area);

this.add(jsp, BorderLayout.NORTH);

this.add(panel, BorderLayout.CENTER);

this.add(text, BorderLayout.SOUTH);

pack();

SendListener sendListener = new SendListener();

btn_send.addActionListener(sendListener);

text.addActionListener(sendListener);

btn_clear.addActionListener(new ActionListener() {

public void actionPerformed(ActionEvent e) {

text.setText("");

area.setText("");

text.requestFocus();

}

});

//窗体监听

this.addWindowListener(new WindowAdapter() {

public void windowClosing(WindowEvent e) {

disConnect();

System.exit(0);

System.out.println("窗体关闭了");

}

}

setVisible(true);

connect();

ClientThread client = new ClientThread();

new Thread(client).start();

setTitle(userName);

}

//监听发送信息方法

private class SendListener implements ActionListener{

public void actionPerformed(ActionEvent e) {

String str = text.getText();

//area.setText(area.getText() + str + "   " + sdf.format(new Date()) + "\n");

text.setText("");

text.requestFocus();

try {

bw.write( userName + " : " + str);

bw.newLine();

bw.flush();

} catch (IOException e1) {

e1.printStackTrace();

}

}

}

//连接服务器方法

public void connect(){

try {

socket = new Socket("127.0.0.1", 8888);

br = new BufferedReader(new InputStreamReader(socket.getInputStream()));

bw = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));

connected = true;

new SetNameJTextField(this);

} catch (UnknownHostException e) {

System.out.println("端口错误!" + e.getMessage());

} catch (IOException e) {

e.printStackTrace();

}

}

//关闭方法

public void disConnect(){

if(bw != null){

try {

bw.close();

bw = null;

} catch (IOException e1) {

e1.printStackTrace();

}finally{

if(br != null){

try {

br.close();

br = null;

} catch (IOException e1) {

e1.printStackTrace();

}finally{

if(socket != null){

try {

socket.close();

socket = null;

} catch (IOException e1) {

e1.printStackTrace();

}

}

}

}

}

}

}

//client 读取操作 线程

private class ClientThread implements Runnable {

String str = null;

public void run() {

try {

while(connected){

while((str = br.readLine()) != null){

String s = str +"    "+ sdf.format(new Date()) + "\n";

area.setText( area.getText() + s);

//设置JTextArea内容过多是聚焦

area.setCaretPosition(area.getText().length());

System.out.println("Server to Client..." + str);

}

}

} catch (IOException e) {

System.out.println("Client 退出了!");

System.exit(0);

}

}

}

//设置名字窗体

private class SetNameJTextField extends JFrame{

JButton btn_setName = null;

Client c =null;

public SetNameJTextField(final Client c){

JFrame frame = new JFrame();

this.c = c;

frame.setTitle("Scanner UserName...");

frame.setSize(300, 130);

frame.setLocation(550, 250);

JPanel panel = new JPanel();

jname = new JTextField(16);

btn_setName = new JButton("OK");

panel.add(new JLabel("UserName:"));

panel.add(jname);

panel.add(btn_setName);

frame.add(panel);

frame.setVisible(true);

SetUserNameListener nameListener = new SetUserNameListener(c, frame);

btn_setName.addActionListener(nameListener);

jname.addActionListener(nameListener);

}

}

private class SetUserNameListener implements ActionListener{

JFrame f = null;

Client client = null;

public SetUserNameListener(Client c, JFrame f){

this.client = c;

this.f = f;

}

public void actionPerformed(ActionEvent e) {

try {

name_buf = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));

userName = jname.getText();

client.setTitle(userName);

name_buf.write(userName);

name_buf.newLine();

name_buf.flush();

//buf.close();

f.dispose();

} catch (IOException e1) {

e1.printStackTrace();

}

}

}

}

五、运行结果

六、实习心得和体会

这次的课程设计是简单聊天程序,在平日的生活学习中我们也经常用,比如QQMSN等即时通讯软件,所以这个课程设计很有现实意义,做起来也比较感兴趣。此次编程的一对多聊天工具利用了java socket套接字编程,由于对于才刚开始学习java语言,由于对java语言的不熟悉,花费了很多时间在对用到的java语言的学习,另外也搜索了一些关于JAVA socket编程的知识,关于服务器与客户端之间的通信主要借用socket编程,由serversocket soc=new serversocket(10000)构造对象监视服务器的10000端口,socket=soc.accept();产生阻塞等待客户端连接,客户端由Socket soc=new Socket(172.0.0.110000)与服务器产生连接。Socket对象得到输入流,并构造相应的BufferedReader对象,由socketd对象得到输出流,服务器从客户端发出的输入流读取信息,编程完时程序不能运行成功,服务器与客户端并不能一对多的聊天,且不能循环,后来询问了学习java的同学,还是没有能找到原因,有在网上搜索一下,也没能有结果,后来我将System.out.println("server:"+is.readLine());从输入流读取服务器信息改为从标准输入读取信息,才运行出正确结果。通过这次实验,我全面的认识到,计算机网络方面的知识学得不够扎实,不能将知识运用到实践中去。以后要注意加强。

本文来源:https://www.2haoxitong.net/k/doc/5c13e7353968011ca300912f.html

《实现一个一对多的聊天程序.doc》
将本文的Word文档下载到电脑,方便收藏和打印
推荐度:
点击下载文档

文档为doc格式