之前在前面已经介绍了Socket通信的一些基本原理,以及如何让客户端与服务器端建立通信,和实现通信的一些基本步骤(包括首先使得服务器端与客户端建立连接,建立连接之后,服务器端开始侦听客户端的请求,侦听到客户端的请求之后,通过输入输出流处理相关信息实现通信,最后通信完毕结束通信等一系列流程)。
但是之前只是单个客户端与服务器进行通信,而我们实际应用中单个客户端的情况几乎不存在,都是多个客户端同时与服务器进行交互(这里同时交互就会出现并发性的问题,对于并发性的问题暂时还不是很懂,只知道有这个概念),那就需要服务器端不停的侦听客户端的请求(写在while循环中,并且条件始终为true,死循环),每当侦听到一个客户端的请求时,都需要创建一个Socket与之建立通信(通过线程实现,每当侦听到一个客户端的请求,服务端都要单独开辟一条线程与之进行通信)。
下面直接贴代码吧:
1、服务端Socket,(这里面通过死循环让服务器端一直循环侦听来自客户端的请求)
需要注意的是,服务端必须要先于客户端启动,因为要启动之后才能侦听客户端的请求
- package com.socket;
- import java.io.IOException;
- import java.net.ServerSocket;
- import java.net.Socket;
- /**
- * 服务器端Socket
- * @author feizi
- * @time 2014-11-14下午5:08:16
- */
- public class ServerSocketMany {
- /**
- * main测试方法
- * @param args
- * @throws IOException
- */
- public static void main(String[] args) throws IOException{
- System.out.println("服务器已经启动,等待客户端的连接....");
- //创建服务器端Socket,即ServerSOcket,等待客户端的请求
- ServerSocket server = new ServerSocket(5555);
- int count = 0;//侦听到的客户端的数量
- Socket socket = null;//服务器端Socket
- //死循环,让服务端循环侦听
- while(true){
- //服务端开始侦听客户端的连接
- socket = server.accept();
- //启动线程,与客户端进行通信
- Thread serverThread = new ServerThread(socket);
- serverThread.start();
- //计数,统计客户端连接数
- count++;
- System.out.println("当前链接的客户端的数量为:"+count+"个....");
- }
- }
- }
package com.socket;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
/**
* 服务器端Socket
* @author feizi
* @time 2014-11-14下午5:08:16
*/
public class ServerSocketMany {
/**
* main测试方法
* @param args
* @throws IOException
*/
public static void main(String[] args) throws IOException{
System.out.println("服务器已经启动,等待客户端的连接....");
//创建服务器端Socket,即ServerSOcket,等待客户端的请求
ServerSocket server = new ServerSocket(5555);
int count = 0;//侦听到的客户端的数量
Socket socket = null;//服务器端Socket
//死循环,让服务端循环侦听
while(true){
//服务端开始侦听客户端的连接
socket = server.accept();
//启动线程,与客户端进行通信
Thread serverThread = new ServerThread(socket);
serverThread.start();
//计数,统计客户端连接数
count++;
System.out.println("当前链接的客户端的数量为:"+count+"个....");
}
}
}
- package com.socket;
- import java.io.BufferedReader;
- import java.io.IOException;
- import java.io.InputStream;
- import java.io.InputStreamReader;
- import java.io.OutputStream;
- import java.io.PrintWriter;
- import java.net.Socket;
- /**
- * 创建一个服务端线程,循环侦听客户端的请求,多个客户端
- * @author feizi
- * @time 2014-11-14下午5:36:45
- */
- public class ServerThread extends Thread{
- //每当侦听到一个新的客户端的时,服务端这边都要有一个Socket与之进行通信
- public Socket socket = null;
- //默认的构造方法,保留
- public ServerThread(){}
- //带参构造方法
- public ServerThread(Socket socket){
- this.socket = socket;
- }
- //覆写run方法
- public void run(){
- //获取输入字节流
- InputStream in = null;
- //将输入字节流包装成输入字符流
- InputStreamReader isr = null;
- //为字符输入流添加缓冲
- BufferedReader br = null;
- //收到信息之后,向客户端响应信息,获取输出字节流
- OutputStream out = null;
- //将字节输出流包装成字符打印输出流
- PrintWriter pw = null;
- try {
- in = socket.getInputStream();
- isr = new InputStreamReader(in);
- br = new BufferedReader(isr);
- //读取字符输入流中的数据
- String data = null;
- while((data = br.readLine()) != null){
- System.out.println("我是服务器,客户端说:"+data);
- }
- //调用shutDown方法关闭Socket输入流
- socket.shutdownInput();
- out = socket.getOutputStream();
- pw = new PrintWriter(out);
- pw.write("用户名和密码正确");
- pw.flush();
- //调用shutDown方法关闭Socket输出流
- socket.shutdownOutput();
- } catch (IOException e) {
- e.printStackTrace();
- }finally{
- //关闭资源
- try {
- if(null != pw)
- pw.close();
- if(null != out)
- out.close();
- if(null != br)
- br.close();
- if(null != isr)
- isr.close();
- if(null != in)
- in.close();
- if(null != socket)
- socket.close();
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- }
- }
package com.socket;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.Socket;
/**
* 创建一个服务端线程,循环侦听客户端的请求,多个客户端
* @author feizi
* @time 2014-11-14下午5:36:45
*/
public class ServerThread extends Thread{
//每当侦听到一个新的客户端的时,服务端这边都要有一个Socket与之进行通信
public Socket socket = null;
//默认的构造方法,保留
public ServerThread(){}
//带参构造方法
public ServerThread(Socket socket){
this.socket = socket;
}
//覆写run方法
public void run(){
//获取输入字节流
InputStream in = null;
//将输入字节流包装成输入字符流
InputStreamReader isr = null;
//为字符输入流添加缓冲
BufferedReader br = null;
//收到信息之后,向客户端响应信息,获取输出字节流
OutputStream out = null;
//将字节输出流包装成字符打印输出流
PrintWriter pw = null;
try {
in = socket.getInputStream();
isr = new InputStreamReader(in);
br = new BufferedReader(isr);
//读取字符输入流中的数据
String data = null;
while((data = br.readLine()) != null){
System.out.println("我是服务器,客户端说:"+data);
}
//调用shutDown方法关闭Socket输入流
socket.shutdownInput();
out = socket.getOutputStream();
pw = new PrintWriter(out);
pw.write("用户名和密码正确");
pw.flush();
//调用shutDown方法关闭Socket输出流
socket.shutdownOutput();
} catch (IOException e) {
e.printStackTrace();
}finally{
//关闭资源
try {
if(null != pw)
pw.close();
if(null != out)
out.close();
if(null != br)
br.close();
if(null != isr)
isr.close();
if(null != in)
in.close();
if(null != socket)
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
3、客户端Socket,这个和单客户端的情况一样,在第一篇中有详细介绍
- package com.socket;
- import java.io.BufferedReader;
- import java.io.IOException;
- import java.io.InputStream;
- import java.io.InputStreamReader;
- import java.io.OutputStream;
- import java.io.PrintWriter;
- import java.net.Socket;
- import java.net.UnknownHostException;
- /**
- * 客户端Socket
- * @author feizi
- * @time 2014-11-14下午5:18:06
- */
- public class ClientSocketDemo {
- /**
- * main测试方法
- * @param args
- * @throws UnknownHostException
- * @throws IOException
- */
- public static void main(String[] args) throws UnknownHostException, IOException{
- //创建客户端Socket,向服务器发起请求
- // String address = "127.0.0.1";
- String address = "localhost";//服务器地址
- int port = 5555;//端口号
- Socket socket = new Socket(address, port);
- //获取Socket的字节输出流
- OutputStream out = socket.getOutputStream();
- //将字节输出流包装成字符打印输出流
- PrintWriter pw = new PrintWriter(out);
- // pw.print("用户名:admin,密码:123");
- // pw.print("用户名:tom,密码:456");
- // pw.print("用户名:dark,密码:789");
- // pw.print("用户名:white,密码:111");
- pw.print("用户名:green,密码:222");
- //刷新输出流
- pw.flush();
- //调用shutDown方法关闭Socket的输出流
- socket.shutdownOutput();
- //接收服务器端发来的响应信息,获取字节输入流
- InputStream in = socket.getInputStream();
- //将字节输入流包装成字符输入流
- InputStreamReader isr = new InputStreamReader(in);
- //为字符输入流添加缓冲
- BufferedReader br = new BufferedReader(isr);
- //读取字符输入流中的数据信息
- String data = null;
- while((data = br.readLine()) != null){
- System.out.println("我是客户端,服务器说:"+data);
- }
- //调用shutDown方法关闭Socket的输入流
- socket.shutdownInput();
- br.close();
- isr.close();
- in.close();
- pw.close();
- out.close();
- socket.close();
- }
- }
package com.socket;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.Socket;
import java.net.UnknownHostException;
/**
* 客户端Socket
* @author feizi
* @time 2014-11-14下午5:18:06
*/
public class ClientSocketDemo {
/**
* main测试方法
* @param args
* @throws UnknownHostException
* @throws IOException
*/
public static void main(String[] args) throws UnknownHostException, IOException{
//创建客户端Socket,向服务器发起请求
// String address = "127.0.0.1";
String address = "localhost";//服务器地址
int port = 5555;//端口号
Socket socket = new Socket(address, port);
//获取Socket的字节输出流
OutputStream out = socket.getOutputStream();
//将字节输出流包装成字符打印输出流
PrintWriter pw = new PrintWriter(out);
// pw.print("用户名:admin,密码:123");
// pw.print("用户名:tom,密码:456");
// pw.print("用户名:dark,密码:789");
// pw.print("用户名:white,密码:111");
pw.print("用户名:green,密码:222");
//刷新输出流
pw.flush();
//调用shutDown方法关闭Socket的输出流
socket.shutdownOutput();
//接收服务器端发来的响应信息,获取字节输入流
InputStream in = socket.getInputStream();
//将字节输入流包装成字符输入流
InputStreamReader isr = new InputStreamReader(in);
//为字符输入流添加缓冲
BufferedReader br = new BufferedReader(isr);
//读取字符输入流中的数据信息
String data = null;
while((data = br.readLine()) != null){
System.out.println("我是客户端,服务器说:"+data);
}
//调用shutDown方法关闭Socket的输入流
socket.shutdownInput();
br.close();
isr.close();
in.close();
pw.close();
out.close();
socket.close();
}
}
下面是程序运行结果截图:
客户端:
服务器端:
大家可以点此链接查看单客户端与服务器端交互的情况:
每天成长一点点,始终坚信:天道酬勤,努力了,奋斗了,一切切有可能!