Java socket 基于TCP/IP 协议应用

多线程服务器原理:

1、          服务器端创建serversocket并绑定要监听的端口号 ,循环调用serversoket 的accept()方法,等待客户端的连接请求

2、          客户端创建一个socket绑定服务器端的IP地址和服务器监听的端口号并请求和服务器端连接

3、          服务器端接收到客户端的请求后,创建一个socket与客户端建立专线连接

4、          建立连接的两个socket在一个单独的线程上对话

5、          服务器端继续等待新的连接

socket.shutdownOutput();和socket.shutdownInput() 注意区分

注意:客户端向服务器端传送数据的时候大多时候将数据封装成一个对象,而不是本文中使用的字符串

Socket socket = new Socket( "localhost",8888);
 OutputStream os = socket.getOutputStream();
 //使用ObjectOutputStream 对象序列化流,传递对象
 ObjectOutputStream objectOutputStream =new ObjectOutputStream(os);
 User user = new User("最帅的","123");//将数据封装为user对象
 //序列化
 objectOutputStream.writeObject(user);
 socket.shutdownOutput();
 BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
 String info = br.readLine();
 while(info != null){
     System.out.println("这里是客户端,服务器传来消息:"+info);
     info =br.readLine(); 
 
传递文件
objectInputStream clientInputStream = null;
 //下载后首先生成一个临时文件
 String fileNaemTemp = "temp.txt";
 String downloadPath = ConfigManager.getInstance(0.getString(Constants.CLIENT_DOWNLOAD_PA
 try{
     clientInputStream = new ObjectInputStream(clientSocket.getInputStream());
     File fileTemp = new File(downloadPath + "/"+fileNaemTemp);
     if(fileTemp.exists()){
         fileTemp.delete();
     }
     fileTemp.createNewFile();
     BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(new FileOutputStream(fileTemp));
     //接受服务器的文件
     byte [] buf = new byte[1024];
     int len;
     while((len= clientInputStream.read(buf)) != -1){
         bufferedOutputStream.write(buf,0,len);
         bufferedOutputStream.flush(); 
客户端:
import java.net.Socket;

/**
  * @描述:客户端
  * Created by Jim Calark on 2017/3/17.
  */public class Client {
     public static void main(String[] args) {


         try {
             //创建客户端socket,指定服务器IP地址和端口号
             Socket  socket = new Socket("localhost",65533);//获取socket 输出流
             OutputStream os =socket.getOutputStream();/将字节输出流转为打印流
             PrintWriter pw = new PrintWriter(os); //输出到服务器端
             pw.write("你好,我是客户端");//冲流
             pw.flush();//pw.close()//这里不能关闭输出流,会导致socket也会关闭;关闭socke 
//的时候会自动关闭该socket下的输出流
//关闭输出流    关错了,关到输入流了 告诉服务器端消息发送完毕
//不关闭该输出流的情况下,会一直卡在线程中读取数据那里

             socket.shutdownOutput();           


             //获取 socket输入流,读取服务器端响应信息
             InputStream is =socket.getInputStream();//将字节流转换为字符流,提高读取效率
             InputStreamReader isr = new InputStreamReader(is);//为字符流设立缓冲区
             BufferedReader br = new BufferedReader(isr);
            String data = null;//循环读取数据
             while((data = br.readLine()) != null){
                 System.out.println(data);

             }
             //关闭资源
             is.close();
             isr.close();
             br.close();
             pw.close();
             socket.close();
         } catch (IOException e) {
             e.printStackTrace();
         }


     }
 }

通信线程类

import java.io.*;

import java.net.Socket;


/**

 * @描述:线程服务类

 * Created by Jim Calark on 2017/3/17.

 */


public class ServerThread  extends Thread{

    /** 和本线程有关的socket */

         Socket socket = null;

     //以socket 为参数的构造器

     public ServerThread (Socket socket){

         this.socket = socket;

     }

     //线程执行的操作,响应客户的请求

     public void run(){

        InputStream  is = null;

        OutputStream os = null;

        BufferedReader br = null;

        InputStreamReader isr = null;

        PrintWriter pw =  null;



        try {


            //获取socket中客户端请求的字节输入流

            is = socket.getInputStream();

            //将字节输入流转为字符输入流

            isr = new  InputStreamReader(is);

            //建立缓冲区,提高数据读取效率

            br = new BufferedReader(isr);

            String data = null ;

            //循环读取数据,每次读取一行

            while((data = br.readLine())!= null){

                //打印数据

                System.out.println("客户端传来的消息"+data);

            }
socket.shutdownInput();//关闭输入流


            //获取输出流响应客户端请求

            os = socket.getOutputStream();

            pw = new PrintWriter(os);

            pw.write("欢迎连接服务器端!");

            pw.flush();//调用flush()方法将缓冲输出



        } catch (IOException e) {

            e.printStackTrace();

        }

        finally {

           //关闭资源

            try{

                if(is !=null){

                    is.close();

                }

                if(isr != null){

                    isr.close();

                }

                if(br != null){

                    br. close();

                }

                if ( os !=  null){

                    os.close();

                }

                if(pw != null){

                    pw.close();


                }

                if(socket != null){

                    socket.close();

                }


            }catch (IOException e){

                e.printStackTrace();

            }




        }



    }

 

服务器端

import java.io.IOException;

import java.net.ServerSocket;

import java.net.Socket;

/**

 * @描述:服务器端类

 * Created by Jim Calark on 2017/3/17.

 */
public class Server {

    public static void main(String[] args) {


        try {

            //创建一个服务器端ServerSocket类,绑定要监听的端口号

            ServerSocket serverSocket = new ServerSocket(65533);

            Socket socket = null;

            //记录客户端连接的数量

            int  count = 0;

            System.out.println("**********服务器即将启动,等待客户端的连接********************");

            //循环监听等待客户端的连接

            while(true){

                //调用ServerSocket 的accept() 开始方法监听,等待客户端的连接,一旦连接就创建一个服务器端的Socket

                 socket = serverSocket.accept();

                //为一个新的连接创建一个新线程

                ServerThread serverThread = new ServerThread(socket);



//设置线程的优先级,范围为[1,10],默认为5。未设置优先级可能会导致运行时速度



//非常慢,可降低优先级



serverThread.setPriority(4);

                //启动线程

                serverThread.start();

                count++;

                System.out.println("当前共"+count + "个客户端连接");

            }

        } catch (IOException e) {

            e.printStackTrace();

        }


    }

}