Java多线程TCP客户端与服务器间使用Socket通信
2016-03-10 13:25
726 查看
Socket是一个有效的网络通信的工具,下面这个简单例子给大家演示一下如何使用Socket来做服务器与客户端之间的通信
客户端代码
/** * @author Jian * 客户端 */ public class Client { public static void main(String[] args) { try { //1.创建客户端Socket,指定服务器地址和端口,本机也可以为localhost Socket socket= new Socket("127.0.0.1", 1344); //2.获取输出流,向服务器端发送登录信息 OutputStream os = socket.getOutputStream();//字节输出流 *//** * 可以装饰为打印流,也可以采用下装饰为字符输出流,使用缓冲来写入 * PrintWriter pw = new PrintWriter(os);//输出流包装为打印流 *//* OutputStreamWriter osw = new OutputStreamWriter(os); BufferedWriter pw = new BufferedWriter(osw); pw.write("用户名:admin;密码:123"); pw.flush();//调用flush()刷新缓存 //关闭输出流 socket.shutdownOutput(); //3.获取输入流,读取服务器端相应信息 InputStream is = socket.getInputStream(); InputStreamReader isr = new InputStreamReader(is);//字节流转换为字符流 BufferedReader br = new BufferedReader(isr);//为输入流添加缓冲 String info = null; while((info=br.readLine())!=null){//循环读取服务器端响应信息 System.out.println("服务器端信息:"+info); } //4.关闭相关资源 br.close(); isr.close(); is.close(); pw.close(); osw.close(); os.close(); socket.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } }
服务器端代码
/** * @author Jian * 基于TCP协议的Socket通信,实现用户登录 * 服务器端 */ public class Server { /*public static void main(String[] args) { try { //1.创建一个服务器端Socket,即ServerSocket,指定绑定的端口,并监听此端口 ServerSocket serverSocket = new ServerSocket(1344); //2.调用accept()方法,等待客户端的连接 System.out.println("-----服务器即将启动,等待客户端连接"); Socket socket = serverSocket.accept();//阻塞式 //3.获取输入流,并读取客户端信息 InputStream is = socket.getInputStream();//字节输入流 InputStreamReader isr = new InputStreamReader(is);//字节流转换为字符流 BufferedReader br = new BufferedReader(isr);//为输入流添加缓冲 String info = null; while((info=br.readLine())!=null){//循环读取 System.out.println("服务器收到的客户端数据"+info); } // socket.shutdownInput();//关闭输入流 //4.获取输出流,响应客户端的请求 OutputStream os = socket.getOutputStream(); PrintWriter pw = new PrintWriter(os); pw.write("Welcome!"); pw.flush();//刷新缓存 //5.关闭相关资源 pw.close(); os.close(); br.close(); isr.close(); is.close(); socket.close(); serverSocket.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } }*/
在客户端的代码中,发送完数据后需要调用shutdownOutput()来告诉服务器端已经发送完毕,这样会使得接下来再利用输出流来向服务器发送信息,所以我们可以将代码稍加修改
服务器端
DataInputStream dis = new DataInputStream(is); int flag = 0; while(true){//循环读取 flag = br.read(); System.out.println(flag); if(flag==1){ String data = dis.readUTF(); System.out.println(data); } break; }
客户端
DataOutputStream dos = new DataOutputStream(os); pw.write(1); pw.flush(); dos.writeUTF(("用户名:admin;密码:123")); dos.flush();//调用flush()刷新缓存 //关闭输出流 //socket.shutdownOutput();
这里我们可以先约定好通信协议,传数字代表的含义,然后可以在服务器端的监听中调用别的方法,使用DataInputStream的readUTF()方法可以读取整段文字,你可以自行设计方法,来避免shutdownIn/Output()后造成无法读写的问题。
尝试一下多线程下的Socket通信
客户端没有什么变化,只要让Server保持死循环监听,每有一个客户端连接进来,就开启一个线程,并在这个线程里与客户端进行通信,具体代码如下:服务器端
//1.创建一个服务器端Socket,即ServerSocket,指定绑定的端口,并监听此端口 ServerSocket serverSocket = new ServerSocket(1344); //2.调用accept()方法,等待客户端的连接 System.out.println("-----服务器即将启动,等待客户端连接"); Socket socket = null; //記錄客戶端數量 int count = 0; while(true){ socket = serverSocket.accept();//阻塞式 //創建一個新的線程 ServerThread serverThread = new ServerThread(socket); serverThread.start(); count++; System.out.println("客戶端數量:"+count); InetAddress address = socket.getInetAddress(); System.out.println("當前客戶端的IP:"+address.getHostAddress()); } // serverSocket.close();
线程类
/** * @author Jian * 服务器端线程处理类 */ public class ServerThread extends Thread{ //和本线程相关的Socket Socket socket = null; public ServerThread(Socket socket) { this.socket = socket; } //线程的操作,响应客户端请求 public void run(){ InputStreamReader isr=null; InputStream is=null; BufferedReader br=null; OutputStream os=null; PrintWriter pw=null; //3.获取输入流,并读取客户端信息 try { is = socket.getInputStream(); isr = new InputStreamReader(is);//字节流转换为字符流 br = new BufferedReader(isr);//为输入流添加缓冲 String info = null; while((info=br.readLine())!=null){//循环读取 System.out.println("服务器收到的客户端数据"+info); } socket.shutdownInput();//关闭输入流 //4.获取输出流,响应客户端的请求 os = socket.getOutputStream(); pw = new PrintWriter(os); pw.write("Welcome!"); pw.flush();//刷新缓存 } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); }finally{ //5.关闭相关资源 try { if(pw!=null) pw.close(); if(os!=null) os.close(); if(br!=null) br.close(); if(isr!=null) isr.close(); if(is!=null) is.close(); if(socket!=null) socket.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } }
这里列举的只是基本的用法,希望能对你有所帮助,大家还需要多加练习,加油!
相关文章推荐
- 网络编程
- 博客搬迁至http://blog.lizorn.com/
- 并发ping监测网络状态
- tcpcopy 1.0 安装使用
- 简单的异步HTTP服务端和客户端
- TCP和UDP
- androd 网络请求方式对比与详解
- Android Volley完全解析(二),使用Volley加载网络图片
- wininet,winhttp,xmlhttprequest,ServerXmlHttpRequest区别
- 生产环境常见的HTTP状态码列表
- mac os x 查看网络端口情况
- 数据库面试(出自http://blog.csdn.net/u013142781s)
- 获取本地时间和网络时间
- IT公司汇总(网络版)
- 最详细的 HTTPS 科普扫盲帖
- tcp四次挥手 close_wait内幕
- HTTP协议具体解释
- 使用PHP类TCPDF生成PDF文档
- HTTP 错误 500.22 - Internal Server Error
- redis 安装和配置http://www.cnblogs.com/liuling/p/2014-4-19-02.html