天天看点

Java中网络编程之TCP协议

一、TCP的基本概念

TCP是专门设计用于在不可靠的英特网上提供可靠的、端到端的字节流通信的协议,是一个面向连接的协议,TCP连接是字节流而非报文流。UDP和TCP各有65536个端口号互不影响。

二、单线程服务端

以下代码只能实现服务端和客户端的同步对话。服务端处理完一个客户端请求,才会处理另一个客户端请求。服务器端的输出效果是Client1阻塞20秒,Client2不会执行。必须等Client1阻塞结束之后,Client2才会执行。该例子可用来学习TCP的基本语法。

/**  

 * TCP客户端1  

 *   

 * @author 徐越  

 */ 

public class Client1  

{  

    public static void main(String[] args) throws Exception  

    {  

        Socket socket = new Socket("127.0.0.1", 8821);  

        OutputStream os = socket.getOutputStream();  

        String msg = "我是徐越1";  

        Thread.sleep(20000);  

        os.write(msg.getBytes());  

        os.flush();  

        os.close();socket.close();    

    }  

}  

 * TCP客户端2  

public class Client2  

        String msg = "我是徐越2";  

 * 单线程TCP服务端  

public class Server  

        // 创建端口为8821的TCP服务器端对象  

        // 8821是服务器端的端口号而客户端从某端口A连到8821,端口A是随机的  

        ServerSocket serverSocket = new ServerSocket(8821);  

        while (true)  

        {  

            // 若无客户端发送请求则线程在此阻塞,方法不继续执行  

            Socket socket = serverSocket.accept();  

            System.out.println("connected");  

            InputStream instream = socket.getInputStream();  

            ByteArrayOutputStream bos = new ByteArrayOutputStream();  

            int len = 0;  

            byte[] buffer = new byte[1024];  

            while ((len = instream.read(buffer)) != -1)  

            {  

                bos.write(buffer, 0, len);  

            }  

            instream.close();  

            bos.flush();  

            bos.close();  

            String msg = bos.toString();  

            System.out.println("客户端的IP:" + socket.getInetAddress().getHostAddress());  

            System.out.println("客户端的端口:" + socket.getPort());  

            System.out.println("客户端的信息:" + msg);  

        }  

执行结果

connected

客户端的IP:127.0.0.1

客户端的端口:3775

客户端的信息:我是徐越1

客户端的端口:3787

客户端的信息:我是徐越2

三、多线程服务器

在实际应用中是在服务器上运行一个永久的程序,接收来自其他多个客户端的请求,提供相应的服务。需要利用多线程实现多客户机制。服务器在指定的端口上监听是否有客户请求,一旦监听到就会启动一个专门的服务线程来响应该请求,而服务器本身在启动完线程之后马上又进入监听状态,等待下一个客户的到来。只要将服务端为如下代码,Client1和Client2就会异步执行。

 * 多线程服务端0  

public class MultiThreadServer0  

    // 端口号  

    private int port = 8821;  

    // 服务端  

    private ServerSocket serverSocket;  

    public MultiThreadServer0() throws IOException  

        // 创建服务器端  

        serverSocket = new ServerSocket(port);  

        System.out.println("服务器启动");  

    public void service()  

            Socket socket = null;  

            try 

                // 客户端进行连接时会触发accept方法从而建立连接  

                socket = serverSocket.accept();  

                new MultiThreadHandler(socket).start();  

            catch (Exception e)  

                e.printStackTrace();  

    public static void main(String[] args) throws IOException  

        new MultiThreadServer1().service();  

 * 多线程处理类  

class MultiThreadHandler extends Thread  

    private Socket socket;  

    public MultiThreadHandler(Socket socket)  

        this.socket = socket;  

    private BufferedReader getReader(Socket socket) throws IOException  

        InputStream socketIn = socket.getInputStream();  

        // InputStreamReader为转换流  

        // InputStream本是字节流,现加一个Reader,表示用字符流的方式读取字节流  

        InputStreamReader isr = new InputStreamReader(socketIn);  

        return new BufferedReader(isr);  

    public void run()  

        try 

            BufferedReader br = getReader(socket);  

            String msg = null;  

            while ((msg = br.readLine()) != null)  

                System.out.println("客户端的IP:" + socket.getInetAddress().getHostAddress());  

                System.out.println("客户端的端口:" + socket.getPort());  

                System.out.println("客户端的信息:" + msg);  

        catch (IOException e)  

            e.printStackTrace();  

        finally 

                if (socket != null)  

                {  

                    socket.close();  

                }  

            catch (IOException e)  

 * 多线程服务端1  

public class MultiThreadServer1  

    // 线程池  

    private ExecutorService executorService;  

    // 单个CPU线程池大小  

    private final int POOL_SIZE = 10;  

    public MultiThreadServer1() throws IOException  

        // 获取当前系统的CPU数目  

        int cpuNums = Runtime.getRuntime().availableProcessors();  

        // 根据系统资源情况灵活定义线程池大小  

        executorService = Executors.newFixedThreadPool(cpuNums * POOL_SIZE);  

                // 客户进行连接就会触发accept方法从而建立连接  

                // 调用线程池操作  

                executorService.execute(new Handler(socket));  

class Handler implements Runnable  

    public Handler(Socket socket)  

 两个多线程服务端执行结果相同

服务器启动

客户端的端口:3931

客户端的端口:3928

参考地址:http://www.2cto.com/kf/201209/158518.html

本文转自IT徐胖子的专栏博客51CTO博客,原文链接http://blog.51cto.com/woshixy/1098701如需转载请自行联系原作者

woshixuye111