我之前写过一篇博客,主要是基于TCP协议实现的聊天室swing版,在此再写一个基于TCP协议实现的聊天室控制台版,便于学习和比较。

package 聊天室console版.utils;

import java.net.InetAddress;
import java.net.UnknownHostException;
/**
* 工具类,服务器端的有关信息
* @author 李章勇
*
*/
public abstract class HostInfo {
//访问权限,供不同包访问
public static String ip=getIp();
public static final int port=10086;
public static final int num=50; private static String getIp(){
try {
return InetAddress.getLocalHost().getHostAddress();
} catch (UnknownHostException e) {
e.printStackTrace();
return null;
}
}
}
-------------------------------------------------------
package 聊天室console版.utils; import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
/**
* 工具类,释放资源
* @author 李章勇
*
*/
public abstract class Release { //访问权限,public,可以供不同包的对象访问 public static void release(Socket socket,BufferedWriter bw){
release(null,socket,null,bw);
} public static void release(Socket socket,BufferedReader br){
release(null,socket,br,null);
} public static void release(Socket socket){
release(null,socket,null,null);
} public static void release(ServerSocket server){
release(server,null,null,null);
} public static void release(ServerSocket server,Socket socket,BufferedReader br,BufferedWriter bw){
if(server!=null){
try {
server.close();
} catch (IOException e) {
System.err.println("服务器创建失败!");
}
}
if(socket!=null){
try {
socket.close();
} catch (IOException e) {
System.err.println("客户端创建失败!");
}
}
if(br!=null){
try {
br.close();
} catch (IOException e) {
System.err.println("输入流创建失败!");
}
}
if(bw!=null){
try {
bw.close();
} catch (IOException e) {
System.err.println("输出流创建失败!");
}
}
} }
--------------------------------------------------------------------
package 聊天室console版.server; import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List; import 聊天室console版.utils.HostInfo;
import 聊天室console版.utils.Release;
/**
* 服务器端类
* 要先开启服务器,再开启客户端
* @author 李章勇
*
*/
public class Server { //仅可以在同一包内访问 涉及查询和增删 用ArrayList集合
static List<Transport> clients=new ArrayList<>(); //服务器构造器
public Server(){ //创建服务器套接字,工具类中的属性
ServerSocket server=null;
try {
server=new ServerSocket(HostInfo.port);
} catch (IOException e) {
Release.release(server);
throw new RuntimeException("服务器端口被占!启动服务器失败!");
} System.out.println("服务器开启成功!"); //接收来自客户端的连接请求,最多接收50个
int num=0;
Socket socket=null;
while(num<HostInfo.num){
try {
socket=server.accept();
} catch (IOException e) {
//释放资源,结束本次循环,进行下一轮循环
Release.release(socket);
continue;
}
System.out.println("第 "+(++num)+" 个客户端成功接入!=="
+socket.getInetAddress().getHostAddress()
+":"+socket.getPort()); //另起一个子线程,专门处理与客户端的数据交互,同时传递入该socket对象 Transport
//并将该转发类对象存入一个集合对象
clients.add(new Transport(socket));
} System.err.println("超出服务器负荷!");
Release.release(server);
} //服务器主线程
public static void main(String[] args) {
new Server();
}
}
-------------------------------------------------
package 聊天室console版.server; import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.Socket; import 聊天室console版.utils.Release;
/**
* 服务器端,处理信息(客户端发来的,以及给客户端转发的)
* @author 李章勇
*
*/
public class Transport extends Thread { //访问权限 仅供本类对象使用
private Socket socket;
private String ip; public Transport(Socket socket){
this.socket=socket;
this.ip=socket.getInetAddress().getHostAddress();
this.start();
} @Override
public void run() {
//从客户端获取流
BufferedReader br=null;
BufferedWriter ownbw=null;
try {
br=new BufferedReader(new InputStreamReader(socket.getInputStream()));
ownbw=new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
} catch (IOException e) {
Server.clients.remove(this);
Release.release(socket, br);
throw new RuntimeException("获取流失败!");
} //从客户端流中循环读数据
String str=null;
try {
while((str=br.readLine())!=null){
String[] split = str.split(":", 2);
if(split.length<=1){
ownbw.write("您发送的数据格式有误,请重新发送!");
ownbw.newLine();
ownbw.flush();
}else{
String desip=split[0];
String content=split[1];
//判断对方是否在线,准备给给目标转发信息
BufferedWriter desbw=null;
boolean isOnLine=false;
for(Transport des:Server.clients){
if(desip.equals(des.ip)){
isOnLine=true;
desbw=new BufferedWriter(new OutputStreamWriter(des.socket.getOutputStream()));
desbw.write(ip+" -->对你说:"+content);
desbw.newLine();
desbw.flush();
}
} if(!isOnLine){
ownbw.write("对方 "+desip+"不在线!");
ownbw.newLine();
ownbw.flush();
}
}
}
} catch (IOException e) {
Server.clients.remove(this);
Release.release(socket, br);
throw new RuntimeException("获取流失败!");
} }
}
-----------------------------------------------------------
package 聊天室console版.client; import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Scanner; import 聊天室console版.utils.HostInfo;
import 聊天室console版.utils.Release;
/**
* 客户端类
* @author 李章勇
*
*/
public class Client {
private Socket socket=null;
public Client(){
//向服务器发起连接请求
try {
socket=new Socket(HostInfo.ip, HostInfo.port);
}catch (IOException e) {
Release.release(socket);
throw new RuntimeException("客户端创建失败!");
} //另建一个子线程从服务器循环读取数据
new Receive().start(); //向服务器循环写流
BufferedWriter bw=null;
Scanner sc=new Scanner(System.in);
String str=null; try {
bw=new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())); while(true){
System.out.println("请发送数据(格式-->对方ip:信息内容):");
str=sc.nextLine();
bw.write(str);
bw.newLine();
bw.flush();
} } catch (IOException e) {
Release.release(socket, bw);
throw new RuntimeException("向服务器写流失败!");
} } private class Receive extends Thread{ @Override
public void run() {
BufferedReader br=null;
try {
br=new BufferedReader(new InputStreamReader(socket.getInputStream()));
} catch (IOException e) {
Release.release(socket, br);
throw new RuntimeException("从服务器获取流失败!");
} String str=null;
//从服务器循环获取流
try {
while((str=br.readLine()) != null){
System.out.println(str);
}
} catch (IOException e) {
Release.release(socket, br);
throw new RuntimeException("从服务器获取流失败!");
} }
} public static void main(String[] args) {
new Client();
} }  

基于TCP协议的聊天室控制台版的更多相关文章

  1. workerman-chat(PHP开发的基于Websocket协议的聊天室框架)(thinkphp也是支持socket聊天的)

    workerman-chat(PHP开发的基于Websocket协议的聊天室框架)(thinkphp也是支持socket聊天的) 一.总结 1.下面链接里面还有一个来聊的php聊天室源码可以学习 2. ...

  2. 网络编程应用:基于TCP协议【实现一个聊天程序】

    要求: 基于TCP协议实现一个聊天程序,客户端发送一条数据,服务器端发送一条数据 客户端代码: package Homework1; import java.io.IOException; impor ...

  3. JavaSE项目之聊天室swing版

    引子: 当前,互联网 体系结构的参考模型主要有两种,一种是OSI参考模型,另一种是TCP/IP参考模型. 一.OSI参考模型,即开放式通信系统互联参考模型(OSI/RM,Open Systems In ...

  4. 分享基于 websocket 网页端聊天室

    博客地址:https://ainyi.com/67 有一个月没有写博客了,也是因为年前需求多.回家过春节的原因,现在返回北京的第二天,想想,应该也要分享技术专题的博客了!! 主题 基于 websock ...

  5. 网络编程----socket介绍、基于tcp协议的套接字实现、基于udp协议的套接字实现

    一.客户端/服务器架构(C/S架构)                                                即C/S架构,包括: 1.硬件C/S架构(打印机) 2.软件C/S架 ...

  6. 基于springboot的websocket聊天室

    WebSocket入门 1.概述 1.1 Http #http简介 HTTP是一个应用层协议,无状态的,端口号为80.主要的版本有1.0/1.1/2.0. #http1.0/1.1/2.0 1.HTT ...

  7. Learning-Python【28】:基于TCP协议通信的套接字

    什么是 Socket Socket 是应用层与 TCP/IP 协议通信的中间软件抽象层,它是一组接口.在设计模式中,Socket 其实就是一个门面模式,它把复杂的 TCP/IP 协议族隐藏在 Sock ...

  8. (2)socket的基础使用(基于TCP协议)

    socket()模块函数用法 基于TCP协议的套接字程序 netstart -an | findstr 8080 #查看所有TCP和UDP协议的状态,用findstr进行过滤监听8080端口 服务端套 ...

  9. 异常处理、socke基于TCP协议编程

    一.异常处理 1.错误和异常 1.程序中难免出现错误,而错误分成两种 (1)语法错误(这种错误过不了Python解释器的语法检测,必须在程序执行前改正) #语法错误示范一 if #语法错误示范二 de ...

随机推荐

  1. 【BZOJ3894】文理分科(最小割)

    [BZOJ3894]文理分科(最小割) 题面 BZOJ Description 文理分科是一件很纠结的事情!(虽然看到这个题目的人肯定都没有纠 结过) 小P所在的班级要进行文理分科.他的班级可以用一个 ...

  2. Round 403 div. 2

    B 可以二分相遇的坐标:也可以二分时间,判断是否存在两个人的区间没有交. An easy way to intersect a number of segments [l1, r1], ..., [l ...

  3. [NOIP2016 D1T3]换教室 【floyd+概率dp】

    题目描述 对于刚上大学的牛牛来说,他面临的第一个问题是如何根据实际情况申请合适的课程. 在可以选择的课程中,有 2n2n 节课程安排在 nn 个时间段上.在第 ii(1 \leq i \leq n1≤ ...

  4. Codeforces 671D. Roads in Yusland(树形DP+线段树)

    调了半天居然还能是线段树写错了,药丸 这题大概是类似一个树形DP的东西.设$dp[i]$为修完i这棵子树的最小代价,假设当前点为$x$,但是转移的时候我们不知道子节点到底有没有一条越过$x$的路.如果 ...

  5. Codeforces 601D. Acyclic Organic Compounds(四个愿望一次满足)

    trie合并的裸题...因为最多只有n个点,所以最多合并n次,复杂度$O(N*26)$. #include<iostream> #include<cstring> #inclu ...

  6. [雅礼集训 2017 Day1]市场

    link 试题分析 可以容易发现此题维护的是一个数据结构,支持区间加,区间除,区间查询最大值.其实就是在$\log$级复杂度内维护除法操作. 我们发现当除数很大或者此串序列大小差不多时,我们令$a_i ...

  7. centos上部署nginx服务

    Nginx ("engine x") 是一个高性能的HTTP和反向代理服务器,也是一个IMAP/POP3/SMTP服务器.Nginx是由Igor Sysoev为俄罗斯访问量第二的R ...

  8. Emgu.CV.CvInvoke”的类型初始值设定项引发异常

    http://zhidao.baidu.com/link?url=VHkw3qZxp7HumQX_r-4ljPiy-N4A7yNK1Xn5q6tjPb16WvBGy6RFKrmKEhtgJ2PACAk ...

  9. 图像灰度化方法总结及其VC实现

    http://blog.csdn.net/likezhaobin/article/details/6915754 最近一段时间作者开始进行运动目标识别定位系统设计,本文以及后续的几篇文章都是从一个图像 ...

  10. R-FCN:基于区域的全卷积网络来检测物体

    http://blog.csdn.net/shadow_guo/article/details/51767036 原文标题为“R-FCN: Object Detection via Region-ba ...