`

Java Tcp Socket聊天系统模型(主要为了学习线程)

阅读更多
TcpSocekt通信模型




Tcp Socket是面向连接的,所以Server端的accept()方法,一直等着客户端的连接,如果连接成功,则两者进行通信,这种是同步的,因为accept()一直在那儿等着,时刻的等着,实际中的聊天系统是采用异步方式,当有请求的时候就调用accept()方法,没有请求的时候该做什么就做什么去,不需要在那儿等着,不浪费资源,一种异步的方式。这个例子只是为了学习线程而准备的。
端口有TCP端口和UDP端口两种,端口号都是从0到65535,TCP端口在3层,UDP不是四层就是7层 TCP和UDP的协议也不相同,TCP比UDP安全,更多TCP和UDP区别上google,baidu。

服务器端编码
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.StringTokenizer;
import java.util.Vector;

/**
 * 服务器端编码
 * @author 欧阳平 2009-3-17 
 */
public class ChatServer {
	static int port = 5566;//端口号
	static Vector<Client> clients = new Vector<Client>(10);//存储连接客户信息
	static ServerSocket server = null; //建立服务器socket
	static Socket socket = null; //套接字连接
	/**
	 * Constructs
	 */
	public ChatServer() {
		try {
			System.out.println("Server start...");
			server  = new ServerSocket(port); //初始化服务器套接字
			while (true) {
				socket = server.accept(); //等待连接
				System.out.println(socket.getInetAddress()+"连接\n");//得到客户机地址
				Client client = new Client(socket); //实例化一个客户线程(其中线程Client中有Socket,这里的的Socket只是起个过度作用)
				//
				clients.add(client);//增加客户线程到向量中
				client.start();//启动线程
				notifyChatRoom(); //监视聊天室连接变化
			}
		} catch (Exception ex) {
			ex.printStackTrace();//输出出错信息
		}
	}
	
	public static void notifyChatRoom() { //监视客户端线程
		StringBuffer newUser = new StringBuffer("newUser");
		for (int i = 0; i < clients.size(); i++) {
			Client c = (Client)clients.elementAt(i);
			newUser.append(":"+c.name); //客户端姓名字符串
		}
		sendClients(newUser);//发送信息到客户端
	}
	
	public static void sendClients(StringBuffer message) {
		for (int i= 0 ; i < clients.size(); i++) {
			Client client = (Client)clients.elementAt(i);//分别得到每个客户端的连接
			client.send(message);//发送信息
		}
	}
	
	public void closeAll() { //关闭所有连接
		while (clients.size() > 0 ) { //遍历整个Vector
			Client client = (Client) clients.firstElement(); //得到一个客户端
			try {
				client.socket.close();
			} catch(IOException ex) {
				ex.printStackTrace(); // 输出错误信息
			}
			clients.removeElement(client); //移出客户端
		}
	}
	
	public static void disconnect(Client c) {// 断开客户端
		try {
			System.err.println(c.ip+"断开连接\n");
		} catch (Exception ex) {
			ex.printStackTrace();
		}
		clients.removeElement(c);
		c.socket = null;
	}
	
	
	/**
	 * main方法
	 * @param args
	 */
	public static void main(String[] args) {
		new ChatServer();

	}
	class Client extends Thread {
		Socket socket;//连接端口
		String name ;//用户姓名
		String ip; //客户端ip地址
		BufferedReader reader;//输入流
		PrintStream ps;//输出流
		public Client(Socket s) {
			socket = s;
			try {
				reader = new BufferedReader(new InputStreamReader(s.getInputStream()));//得到输入流
				ps = new PrintStream(s.getOutputStream());//得到输出流
				String info = reader.readLine();//读取接收到的信息
				StringTokenizer stinfo = new StringTokenizer(info,":"); //分解字符串
				String head = stinfo.nextToken(); //获取关键字
				System.out.println(stinfo.toString());
				System.out.println(head);
				if (stinfo.hasMoreTokens()){
					name = stinfo.nextToken() ;//获取用户名
				}
				if (stinfo.hasMoreTokens()) {
					ip = stinfo.nextToken(); //获取IP地址
				}
			} catch (IOException ex) {
				ex.printStackTrace();
			}
			System.out.println(name);
			System.out.println(ip);
		}
		
		public void send (StringBuffer msg) {
			ps.println(msg); //输出信息
			ps.flush();
		}
		public void run() {
			while (true) {
				String line = null;
				try {
					
					line = reader.readLine();
					System.out.println("line:"+line);
					
				} catch (IOException ex) {
					ex.printStackTrace(); //输出错误信息
					ChatServer.disconnect(this);//断开连接
					ChatServer.notifyChatRoom();//更新信息
					return ;
				}
				if (line == null) { //客户离开
					ChatServer.disconnect(this);
					ChatServer.notifyChatRoom();
					return ;
				}
				StringTokenizer st = new StringTokenizer(line,":");//分解字符串
				String keyword = st.nextToken();
				if (keyword.equals("MSG")) { //发送来的聊天信息
					StringBuffer msg = new StringBuffer("MSG:");
					msg.append(name); //在信息上增加用户名
					msg.append(st.nextToken("\0\n"));
					ChatServer.sendClients(msg);//发送聊天语句到各个客户端
					System.out.println(msg);
				} else if (keyword.equals("quit")) { //退出命令
					ChatServer.disconnect(this); //断开连接
					ChatServer.notifyChatRoom(); //刷新信息
				}
			}
		}
	}
	
}




//客户端编码
import java.awt.BorderLayout;
import java.awt.Button;
import java.awt.Color;
import java.awt.Label;
import java.awt.TextArea;
import java.awt.TextField;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.net.InetAddress;
import java.net.Socket;
import java.util.StringTokenizer;

import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;

/**
 * 基于Socket网络聊天程序 客户端编码
 * @author 欧阳平 2009-3-17 
 */
public class ChatClient extends JFrame  implements ActionListener,Runnable{
	
	TextField tfName = new TextField(15);//姓名输入文本域
	Button btConnect = new Button("连接");//连接按钮
	Button btDisconnect = new Button("断开连接");//断开连接按钮
	TextArea tfChat = new TextArea(8,27);//显示聊天信息文本域
	Button btSend = new Button("发送");
	TextField tfMessage = new TextField(30);//聊天输入
	java.awt.List list1  = new java.awt.List(9);//显示在线用户信息 
	Socket socket = null;//连接端口
	PrintStream ps = null;//输出流
	Listen listen = null;
	//监听线程类
	class Listen extends Thread {
		BufferedReader reader;
		PrintStream ps;
		String cname;
		Socket socket;
		ChatClient chatClient;
		public Listen(ChatClient client,String name,Socket socket) {
			try {
				this.chatClient = client;
				 this.socket = socket;
				 this.cname = name;
				 reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
				 ps = new PrintStream(socket.getOutputStream());
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		public void run() {
			while (true) {
				String line=null ;
				try {
				line = reader.readLine(); //读取数据流
				System.out.println("客户端:"+line);
				
			}catch (IOException ex) {
				ex.printStackTrace();
				ps.println("quit");; //断开连接
				return;
			}
			StringTokenizer stinfo = new StringTokenizer(line,":"); //分解字符串
			String keyword = stinfo.nextToken();
			if (keyword.equals("MSG")) {
				chatClient.tfChat.append(line+"\n");
			}
			else if (keyword.equals("newUser")){
				chatClient.list1.clear();
				chatClient.list1.add("users", 0);
				int i = 1;
				while (stinfo.hasMoreTokens()) {
					chatClient.list1.add(stinfo.nextToken(), i++);
				}
			}
	   	}
		
	  }
	}
	public void actionPerformed(ActionEvent e) {
		try{
			if(e.getSource()==btConnect) { //点击连接按钮
				if (socket == null) {
					socket = new Socket(InetAddress.getLocalHost(),5566);//实例化一个套接字
					ps = new PrintStream(socket.getOutputStream());//获取输出流,写入信息
					StringBuffer info = new StringBuffer("info:");
					String userinfo = tfName.getText()+":"+InetAddress.getLocalHost().toString();
					ps.println(info.append(userinfo));//输出信息
					ps.flush();
					listen = new Listen(this,tfName.getText(),socket);
					listen.start();
				}
			} else if (e.getSource() == btDisconnect) { //点击断开连接按钮
				disconnect();
			} else if (e.getSource() == btSend) { //点击发送按钮
				if (socket != null) {
					StringBuffer msg = new StringBuffer("MSG:");
					String msgtxt = new String(tfMessage.getText());
					ps.println(msg.append(msgtxt));//发送信息
					ps.flush();
				} else {
					JOptionPane.showMessageDialog(this, "请先连接!", "提示", 1);
				}
			}
			
		} catch (Exception ex) {
			ex.printStackTrace();//输出错误信息
		}
	}
	public void disconnect() { //断开连接方法
		if (socket != null) {
			ps.println("quit");//发送信息
			ps.flush();
			
			socket = null;
			tfName.setText("");
		}
	}
	
	
	
	
	
	

	
	public ChatClient(Socket socket) {
		
		
		this.setLayout(new BorderLayout());
		
		JPanel panel1 = new JPanel();
		Label label = new Label("姓名");
		panel1.setBackground(Color.orange);
		panel1.add(label);
		panel1.add(tfName);
		panel1.add(btConnect);
		panel1.add(btDisconnect);
		this.add(panel1,BorderLayout.NORTH);
		
		JPanel panel2 = new JPanel();
		panel2.add(tfChat);
		panel2.add(list1);
		this.add(panel2,BorderLayout.CENTER);
		
		JPanel panel3 = new JPanel();
		Label label2 = new Label("聊天信息");
		panel3.add(label2);
		panel3.add(tfMessage);
		panel3.add(btSend);
		this.add(panel3,BorderLayout.SOUTH);
		
		this.setBounds(50,50,400,350);
		this.setVisible(true);
		
		btConnect.addActionListener(this);
		btDisconnect.addActionListener(this);
		btSend.addActionListener(this);
		
	}
	
	/**
	 * @param args
	 */
	public static void main(String[] args) {
		ChatClient client = new ChatClient(new Socket());
		System.out.println(client.socket);
	}


在想做东西的时候,不能只拿着代码就想编程,先搞清楚原理规则,然后动手实践,否则事倍功半!了解规则,熟悉规则。
分享到:
评论
1 楼 salever 2011-09-15  
不错,貌似少一点超时设置

相关推荐

    基于Java的网络聊天系统的设计与实现(源码+说明文档)

    本次课程设计是一个类似于QQ的聊天软件,结合所学Java课程,用Java完成了图形化界面和事件处理、多线程编程、Socket通信、数据库存储,保存通信记录的功能,完成网络聊天软件。进行编程实验,程序代码编写、调试、...

    socket通讯汇总

    用Java实现一个Socket通信模型 pdf 用Java实现网络通讯 pdf 用JAVA实现基于TCP的SOCKET编程 pdf 用Java实现基于TCPIP协议的网络通信程序 pdf 一种基于JAVA多线程的即时显示策略 pdf 利用Java实现网络通信 pdf ...

    socket通讯资料汇总

    用JAVA实现基于TCP的SOCKET编程.pdf 用Java实现基于TCPIP协议的网络通信程序.pdf 一种基于JAVA多线程的即时显示策略.pdf 利用Java实现网络通信.pdf 利用Java进行网络编程.pdf 利用JAVA的SOCKET实现网上交谈.pdf...

    基于JAVA的网络通讯系统设计与实现的毕业设计

    本设计以JAVA语言为基础,设计并实现一个基于TCP/IP协议的网络通讯系统。系统包括服务端和客户端两个部分,服务端负责接收客户端的连接请求,处理客户端的请求并返回相应的结果,客户端负责向服务端发送请求并接收服务端...

    java多线程tcpsocketserver源码-Java-Book:Java学习资料整理

    java多线程tcp socket server源码 Java学习资料整理 框架 / dubbo监控 / / / / / / / / / / / / / / / / / / / / 收藏 / 技术社区 书籍推荐 计算机基础 计算机科学导论 --(如果不是计算机科班的,应先看看计算机基础...

    网络实训基于Java的网络聊天软件的设计与实现

    本文使用的网络编程模型是客户端/服务端(C/S)结构,遵循TCP和UDP协议,网络聊天功能通过socket模块实现,用户在客户端上登录到指定端口的服务端与其他用户进行网络聊天。服务器启动后,等待客户端的连接,转发客户端指定...

    基于javatcpsocket通信的拆包和装包源码-NettyTree:网状树

     1)单线程模型,所有的IO操作都在一个NIO线程上完成   存在性能和可靠性上的问题  2)多线程模型,有一组NIO线程处理IO操作   有一个专门的NIO线程-Acceptor线程用于监听服务端,接收客户端的TCP连接请求;   ...

    java源码包---java 源码 大量 实例

    (2)鼓励间接地(通过程序)使用远程计算机,(3)保护用户因主机之间的文件存储系统导致的变化,(4)为了可靠和高效地传输,虽然用户可以在终端上直接地使用它,但是它的主要作用是供程序使用的。本规范尝试满足...

    java多线程tcpsocketserver源码-netty-learning:网络学习

    java多线程tcp socket server源码@Netty 笔记 1. 内蒂 网络应用框架 特征 设计 支持多种传输类型 事件模型 高度可定制的线程模型 表现 高吞吐量,低延迟 更少的资源消耗 最小化内存拷贝 安全SSL/TLS 支持 建筑学 核 ...

    JAVA上百实例源码以及开源项目源代码

    (2)鼓励间接地(通过程序)使用远程计算机,(3)保护用户因主机之间的文件存储系统导致的变化,(4)为了可靠和高效地传输,虽然用户可以在终端上直接地使用它,但是它的主要作用是供程序使用的。本规范尝试满足...

    smart-socket 开源的Java AIO框架.rar

    smart-socket是一款国产开源的 Java AIO 通信框架,支持 TCP、UDP、SSL/TLS 。 高性能、高并发、低延迟、低能耗 代码量极少,可读性强。核心代码不到 1500 行,工程结构、包层次清晰。 学习门槛低,二次开发只需...

    java源码包4

    (2)鼓励间接地(通过程序)使用远程计算机,(3)保护用户因主机之间的文件存储系统导致的变化,(4)为了可靠和高效地传输,虽然用户可以在终端上直接地使用它,但是它的主要作用是供程序使用的。本规范尝试满足...

    java源码包3

    (2)鼓励间接地(通过程序)使用远程计算机,(3)保护用户因主机之间的文件存储系统导致的变化,(4)为了可靠和高效地传输,虽然用户可以在终端上直接地使用它,但是它的主要作用是供程序使用的。本规范尝试满足...

    java源码包2

    (2)鼓励间接地(通过程序)使用远程计算机,(3)保护用户因主机之间的文件存储系统导致的变化,(4)为了可靠和高效地传输,虽然用户可以在终端上直接地使用它,但是它的主要作用是供程序使用的。本规范尝试满足...

    JAVA上百实例源码以及开源项目

    (2)鼓励间接地(通过程序)使用远程计算机,(3)保护用户因主机之间的文件存储系统导致的变化,(4)为了可靠和高效地传输,虽然用户可以在终端上直接地使用它,但是它的主要作用是供程序使用的。本规范尝试满足...

    smart-socket是一款国产开源的Java AIO通信框架.rar

    Smart-Socket是一款国产开源的 Java AIO 通信框架,支持 TCP、UDP、SSL/TLS 。 作为一款极简、易用、高性能的通信框架,现已广泛运用于物联网、证券、电力、电商等诸多领域。 二、Smart-Socket的优势有哪些? 1.高...

    基于Java的即时通讯系统设计与实现【文献综述】.doc

    二、即时通讯系统的开发语言 开发基于Socket通信的聊天软件 ,该软件采用了客户端/服务器(C/S)体系结构,由于Java是当下最流行的开发语言,它 一开始就内置了对网络编程的支持,它提供的强大的API,可以使程序员很...

    成百上千个Java 源码DEMO 4(1-4是独立压缩包)

    (2)鼓励间接地(通过程序)使用远程计算机,(3)保护用户因主机之间的文件存储系统导致的变化,(4)为了可靠和高效地传输,虽然用户可以在终端上直接地使用它,但是它的主要作用是供程序使用的。本规范尝试满足...

    JAVA清华大学教程

    清华大学java课程学习使用教程 ★ 第一讲 Java语言概述 ◇课前索引 ◇1.1 java语言的发展史 ◇1.2 java的工作原理 ◇1.3 一切都是对象 ◇1.4 构建java程序 ◇1.5 java程序规范 ◇1.6 建立java开发环境 ◇本...

    java包与接口实验报告

    3)网络包(java.net):支持Internet的TCP/IP协议,用于实现Socket编程;提供了与Internet的接口,支持URL连接,WWW的即时访问,并且简化了用户/服务器模型的程序设计。 4)抽象图形用户接口包(javax.swing):实现了...

Global site tag (gtag.js) - Google Analytics