一个完整的项目包括服务器和客服端

服务器端初步编写:

(1)

服务器端应用窗口的编写 (服务器类Server):

包括窗口和组件的一些设置, 添加一些客服端的元素,如客服端在线用户表(Vector), 服务端接口ServerSocket, 服务端线程ServerThread

其次就是组件的事件监听以及相应的事件方法

(2)

服务器线程的编写 (服务器线程类 ServerThread):

服务器线程起分配服务器代理线程作用,接受客服端的连接同时为其分配一个专用的服务器代理线程.

编写相对简单,给出服务器(Server) 通过其服务端接口(ServerSocket)监听客服端的连接(Socket),同时为其分配代理线程(ServerAgentThread)

public class ServerThread extends Thread
{
Server father; //声明Server的引用
ServerSocket ss;//声明ServerSocket的引用
boolean flag=true;
public ServerThread(Server father)
{//构造器
this.father=father;
ss=father.ss;
}
public void run()
{
while(flag)
{
try
{
Socket sc=ss.accept();//等待客户端连接
ServerAgentThread sat=new ServerAgentThread(father,sc);
sat.start();//创建并启动服务器代理线程
}
catch(Exception e)
{
e.printStackTrace();
}
}
}
}

(3)

服务器代理线程(ServerAgentThread) :代理线程对应相应的客服端 起到接受发送信息作用   一个服务器代理线程与一个客服端唯一对应

服务器代理线程类是服务器主要类,

其中包括一些基本的代理线程内容 如服务器(Server)  客服端连接(Socket) 数据输入输出(DateInputStream DateOutputStream)

还有与客服端的数据的一些交流方法, 线程run方法起判断客服端信息作用

public class ServerAgentThread extends Thread
{ Server father;//声明Server(服务器Server)的引用
Socket sc;//声明Socke(客服端接口Socket)t的引用
DataInputStream din;//声明数据输入流与输出流
DataOutputStream dout;
boolean flag=true;//控制线程的生命周期
public ServerAgentThread(Server father,Socket sc)
{
//构造方法一般初始化 服务器 客服端接口 还有应用端接口数据输入输出
this.father=father;
this.sc=sc;
try
{
din=new DataInputStream(sc.getInputStream());//创建数据输入流
dout=new DataOutputStream(sc.getOutputStream());//创建数据输出流
}
catch(Exception e)
{
e.printStackTrace();
}
}
public void run()
{
while(flag)
{
try
{
String msg=din.readUTF().trim();
//接收客户端传来的信息判断并作出相应的回应
//其中单个回应一般包含对服务器端的操作数据回应 以及对客服端的操作数据回应
if(msg.startsWith("c"))//收到新用户的信息
{
this.nick_name(msg);
}
else if(msg.startsWith("<#CLIENT_LEAVE#>")){
this.client_leave(msg);
}
else if(msg.startsWith("<#TIAO_ZHAN#>")){
this.tiao_zhan(msg);
}
else if(msg.startsWith("<#TONG_YI#>")){
this.tong_yi(msg);
}
else if(msg.startsWith("<#BUTONG_YI#>")){
this.butong_yi(msg);
}
else if(msg.startsWith("<#BUSY#>")){
this.busy(msg);
}
else if(msg.startsWith("<#MOVE#>")){
this.move(msg);
}
else if(msg.startsWith("<#RENSHU#>")){
this.renshu(msg);
}
}
catch(Exception e)
{
e.printStackTrace();
}
}
} //单个操作方法的书写
//此处省略几个
//新用户
public void nick_name(String msg)
{
try
{
String name=msg.substring(13);//获得用户的昵称
this.setName(name);//用该昵称给该线程取名
Vector v=father.onlineList;//获得在线用户列表
boolean isChongMing=false;//重名flag
int size=v.size();//获得用户列表的大小
for(int i=0;i<size;i++)
{
//遍历列表,查看是否已经有该用户名
ServerAgentThread tempSat=(ServerAgentThread)v.get(i);
if(tempSat.getName().equals(name))
{
isChongMing=true;//有重名,将标志位设为true
break;
}
}
if(isChongMing==true)//如果重名
{
dout.writeUTF("<#NAME_CHONGMING#>");//将重名信息发送给客户端
din.close();//关闭数据输入流
dout.close();//关闭数据输出流 //重点部分 重名需要终止分配的该服务器代理线程以免产生安全问题
sc.close();//关闭Socket
flag=false;//终止该服务器代理线程
}
else//如果不重名
{
v.add(this);//将该线程添加到在线列表
father.refreshList();//刷新服务器在线信息列表
String nickListMsg="";
size=v.size();//获得在线列表大小
//(实时更新)
for(int i=0;i<size;i++)
{
ServerAgentThread tempSat=(ServerAgentThread)v.get(i);
nickListMsg=nickListMsg+"|"+tempSat.getName();
}
nickListMsg="<#NICK_LIST#>"+nickListMsg;
//将在线用户组成字符串 <#NICK_LIST#>|1|2|3|4|5|6|7
Vector tempv=father.onlineList;
size=tempv.size();
for(int i=0;i<size;i++)
{//遍历在线列表
ServerAgentThread satTemp=(ServerAgentThread)tempv.get(i);
satTemp.dout.writeUTF(nickListMsg);//将最新的列表信息发送到各个客户端
if(satTemp!=this)
{//给其他客户端发送新用户上线的信息
satTemp.dout.writeUTF("<#MSG#>"+this.getName()+"上线了...");
}
}
}
}
catch(IOException e)
{
e.printStackTrace();
} } } //用户下线
public void client_leave(String msg){
try{
Vector tempv=father.onlineList;//获得在线列表
tempv.remove(this);//移除该用户代理线程
int size=tempv.size();
String nl="<#NICK_LIST#>";
for(int i=0;i<size;i++){//遍历在线列表
ServerAgentThread satTemp=(ServerAgentThread)tempv.get(i);
//向各个客户端发送用户离线信息
satTemp.dout.writeUTF("<#MSG#>"+this.getName()+"离线了...");
//组织信息的在线用户列表
nl=nl+"|"+satTemp.getName();
}
for(int i=0;i<size;i++){//将最新的列表信息发送到各个客户端
ServerAgentThread satTemp=(ServerAgentThread)tempv.get(i);
satTemp.dout.writeUTF(nl);
} (重点部分 线程下线需要关闭其相关代理)
this.flag=false;//终止该服务器代理线程
father.refreshList();//更新服务器在线用户列表
}
catch(IOException e){e.printStackTrace();}
}

  

java服务器端线程体会的更多相关文章

  1. Java Socket线程的设计原理介绍

    转自:http://developer.51cto.com/art/201003/190001.htm Java Socket线程我们经常会用到的技术,但是有很多程序员还是有不少的使用问题,下面我们就 ...

  2. java之线程

    java之线程 一:线程: 线程是什么呢?线程,有时被称为轻量级进程是程序执行流的最小单元.一个标准的线程由线程ID,当前指令指针(PC),寄存器集合和堆栈组成.另外,线程是进程中的一个实体,是被系统 ...

  3. Java 使用线程方式Thread和Runnable,以及Thread与Runnable的区别

    一. java中实现线程的方式有Thread和Runnable Thread: public class Thread1 extends Thread{ @Override public void r ...

  4. Java的线程安全

    线程安全 我们这里讨论的线程安全,就限定于多个线程之间存在共享数据访问这个前提,因为如果一段代码根本不会与其他线程共享数据,那么从线程安全的角度来看,程序是串行执行还是多线程执行对它来说是完全没有区别 ...

  5. 深入理解Java之线程池

    原作者:海子 出处:http://www.cnblogs.com/dolphin0520/ 本文归作者海子和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则 ...

  6. java中线程分两种,守护线程和用户线程。

    java中线程分为两种类型:用户线程和守护线程. 通过Thread.setDaemon(false)设置为用户线程: 通过Thread.setDaemon(true)设置为守护线程. 如果不设置次属性 ...

  7. java 多线程—— 线程让步

    java 多线程 目录: Java 多线程——基础知识 Java 多线程 —— synchronized关键字 java 多线程——一个定时调度的例子 java 多线程——quartz 定时调度的例子 ...

  8. java 多线程—— 线程等待与唤醒

    java 多线程 目录: Java 多线程——基础知识 Java 多线程 —— synchronized关键字 java 多线程——一个定时调度的例子 java 多线程——quartz 定时调度的例子 ...

  9. Java的线程模型

    并发不一定要依赖多线程(如PHP中很常见的多进程并发),但是在Java里面谈论并发,大多数都与线程脱不开关系. 线程是比进程更轻量级的调度执行单位,线程的引入,可以把一个进程的资源分配和执行调度分开, ...

随机推荐

  1. Essential C++学习笔记

    1.当我们调用一个函数时,会在内存中建立起一块特殊区域,称为“程序栈”,这块特殊区域提供了每个函数参数的存储空间,它也提供函数所定义的每个对象的内存空间--我们将这些对象称为局部对象.一旦函数完成,这 ...

  2. 【转】python get-pip.py could not find a version that satisfies

    转:https://blog.csdn.net/yanlisuo/article/details/81357305 转:https://blog.csdn.net/dyrlovewc/article/ ...

  3. FlashFXP 5.0.0官方中文破解版,附文件下载地址和破解码

    FlashFXP 5.0.0官方中文破解版是一个功能强大的 FXP/FTP 软件,融合了一些其他优秀 FTP 软件的优点,如像 CuteFTP 一样可以比较文件夹,支持彩色文字显示:像 BpFTP 支 ...

  4. 【转】推荐给初级Java程序员的3本进阶书

    ImportNew 注: 原作者在这篇文章中介绍3本不错的技术书籍.作者认为这些书籍对新手或者学生而言尤其有帮助.通过一些基础性的教程入门后,我们可以使用Java做基础性的编程.然而,当我们需要从初级 ...

  5. MySQL快速回顾:计算字段与函数

    9.1 计算字段 存储在数据库表中的数据一般不是应用程序所需要的格式.比如: 如果想要在一个字段中既显示公司名,又显示公式的地址,但这两个信息一般包含在不同的表列中. 城市.州和邮政编码存储在不同的列 ...

  6. 《【面试突击】— Redis篇》-- Redis的线程模型了解吗?为啥单线程效率还这么高?

    能坚持别人不能坚持的,才能拥有别人未曾拥有的.关注编程大道公众号,让我们一同坚持心中所想,一起成长!! <[面试突击]— Redis篇>-- Redis的线程模型了解吗?为啥单线程效率还这 ...

  7. AVR单片机教程——串口接收

    本文隶属于AVR单片机教程系列.   上一讲中,我们实现了单片机开发板向电脑传输数据.在这一讲中,我们将通过电脑向单片机发送指令,让单片机根据指令控制LED.这一次,两端的TX与RX需要交叉连接,单片 ...

  8. http请求头中的content-type属性

    在HTTP请求中,我们每天都在使用Content-Type来指定不同格式的请求信息,但是却很少有人去全面了解Content-Type中允许的值有多少,因此这里来了解一下Content-Type的可用值 ...

  9. Java单体应用 - Markdown - 02.基础语法

    原文地址:http://www.work100.net/training/monolithic-markdown-basic.html 更多教程:光束云 - 免费课程 基础语法 序号 文内章节 视频 ...

  10. maven报错:Return code is: 501 , ReasonPhrase:HTTPS Required

    今天把一个去年没做完的项目翻出来做时,发现maven无法正常导入依赖.检查了一遍项目配置,没发现有什么问题.而且依赖在本地仓库存在. 随后发现报错:Failed to transfer file:** ...