您的位置:首页 > 其它

使用ServerSocket建立聊天服务器(一)

2017-03-31 20:27 519 查看
-------------siwuxie095

工程名:TestMyServerSocket

包名:com.siwuxie095.socket

类名:MyServerSocket.java(主类)、ServerListener.java、ChatSocket.java

工程结构目录如下:



MyServerSocket.java(主类):

package com.siwuxie095.socket;

/**

*
聊天服务器,仅能向客户端发送数据

*

* @author siwux

*

*/

public class MyServerSocket {

/**

*
这是主类(主线程),启动线程ServerListener进行监听,

*
当有Socket对象进行连接时,在线程ServerListener中

*
启动线程ChatSocket

*

* @param args

*/

public staticvoid main(String[] args) {

//运行线程ServerListener,使用匿名对象

new ServerListener().start();

}

}

ServerListener.java:

package com.siwuxie095.socket;

import java.io.IOException;

import java.net.ServerSocket;

import java.net.Socket;

import javax.swing.JOptionPane;

//创建线程
ServerListener,将有阻塞的代码放到这个独立的线程中

public class ServerListener
extends Thread {

//
复写run()

@Override

publicvoid run() {

try {

//
创建一个ServerSocket对象,并指定端口:12345

//
端口的范围:1~65535,通常都指定较大的数字,

//
这样和较小的或系统预留的端口分开

//
有异常抛出,用 try catch
捕获

ServerSocket serverSocket =
new ServerSocket(12345);

// ServerSocket创建完成后需要侦听客户端的连接

//
调用accept()方法,这是一个阻塞的方法,

//
会阻塞当前的线程,对于有阻塞的代码,应该放到独立的线程中

//(ServerListener
就是一个独立的线程)

//
返回值是Socket类型,创建以接收返回值

//
当accept()被执行且socket被赋值,说明有客户端连接

//每当有一个客户端连接到ServerSocket,accept()都会返回一个新的Socket对象

//如果有多个客户端来连接当前的服务器ServerSocket,就会有多个Socket对象出现

//需要一个while循环来循环监听

while (true) {

Socket socket = serverSocket.accept();

//
建立连接时

//
弹出提示框:有客户端连接到本机的 12345
端口

JOptionPane.showMessageDialog(null,
"有客户端连接到本机的 12345
端口");

//由于每一个socket要与一个独立的客户端进行通信

//所以要将socket传递给新的线程:ChatSocket(用于Socket通信)

//每一个socket都有一个独立的ChatSocket线程

//每一个ChatSocket线程之间是相互独立的,它们不能相互沟通数据

//运行该线程,使用匿名对象

new ChatSocket(socket).start();

}

}
catch (IOException e) {

e.printStackTrace();

}

}

}

ChatSocket.java:

package com.siwuxie095.socket;

import java.io.BufferedWriter;

import java.io.IOException;

import java.io.OutputStream;

import java.io.OutputStreamWriter;

import java.io.UnsupportedEncodingException;

import java.net.Socket;

/**

*
代码段(4)一直包装到带缓冲的字符流,输出时需要flush进行强制输出

*
代码段(3)是简单的字节流进行输出

*

* (4)等效于(3)等效于(1)加(2)

*

* (4)=(3)=(1)+(2)

*

*
主要使用(4),其他注释起来

*

* @author siwux

*

*/

//创建用于Socket通信的线程:ChatSocket

public class ChatSocket
extends Thread {

Socket socket;

//创建构造方法,传入Socket对象

public ChatSocket(Socket socket) {

this.socket=socket;

}

//(1)

publicvoid output(String out) {

try {

//socket.getOutputStream()
即 OutputStream

//实际上是
OutputStream.write() 即 os.write()

//为
getBytes()指定编码

//有异常抛出,用
try catch 捕获

socket.getOutputStream().write(out.getBytes("UTF-8"));

}
catch (UnsupportedEncodingException e) {

e.printStackTrace();

}
catch (IOException e) {

e.printStackTrace();

}

}

//复写run()方法

@Override

publicvoid run() {

// //(2)

// int count=0;

// while (true) {

// output("loop:"+count+"-");

// count++;

// try {

// sleep(1000);

// } catch (InterruptedException e) {

// e.printStackTrace();

// }

// }

// //(3)

// try {

// OutputStream os=socket.getOutputStream();

// int count=0;

// while (true) {

// String outString="loop:"+count+"-";

// byte outByte[]=outString.getBytes("UTF-8");

// os.write(outByte);

// count++;

// sleep(1000);

//

// }

//

// } catch (IOException e) {

// e.printStackTrace();

// } catch (InterruptedException e) {

// e.printStackTrace();

// }

//(4)

try {

//对当前的Socket执行数据输出相关功能的包装

//使用getOutputStream()获取输出流,通过输出流向外输出数据

//返回值是OutputStream类型,创建以接收返回值

OutputStream os=socket.getOutputStream();

//创建一个BufferedWriter作为数据的输出,传入匿名对象,指定编码,层层包装

BufferedWriter bw=new BufferedWriter(new OutputStreamWriter(os,"UTF-8"));

//通过BufferedWriter可以在Socket中直接输出一行字符串

int count=0;

//一直循环

while (true) {

//让BufferedWriter输出字符串

bw.write("loop:"+count+"-");

//因为带缓冲,所以需要强制输出,不然无法输出

bw.flush();

//1秒执行一次

//有异常抛出,用
try catch 捕获

sleep(1000);

count++;

}

}
catch (IOException e) {

e.printStackTrace();

}
catch (InterruptedException e) {

e.printStackTrace();

}

}

}

运行后,终止按钮(Terminate)长亮,即 当前程序正在运行 且 没有停止



而且,此时也没有任何提示框,即当前程序被阻塞在ServerListener.java 的:

Socket socket=serverSocket.accept();

打开CMD 窗口,输入:telnet
127.0.0.1 12345或telnet
localhost 12345

(即本机地址+端口),回车。此时,会弹框提示:



点击确定,CMD 窗口开始无限循环输出:



此时程序并未停止,可以继续打开多个CMD 窗口进行连接,

相当于新建客户端,也是从一开始进行输出

点击终止按钮(Terminate),可结束运行

【made by siwuxie095】
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: