Java中网络编程之TCP协议

来源:互联网 发布:苹果a1429支持什么网络 编辑:程序博客网 时间:2024/05/30 05:08

一、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 *  * @author 徐越 *  */public class Client2{public static void main(String[] args) throws Exception{Socket socket = new Socket("127.0.0.1", 8821);OutputStream os = socket.getOutputStream();String msg = "我是徐越2";os.write(msg.getBytes());os.flush();os.close();socket.close();}}/** * 单线程TCP服务端 *  * @author 徐越 *  */public class Server{public static void main(String[] args) throws Exception{// 创建端口为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
connected
客户端的IP:127.0.0.1
客户端的端口:3787
客户端的信息:我是徐越2

 

三、多线程服务器

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

/** * 多线程服务端0 *  * @author 徐越 *  */public class MultiThreadServer0{// 端口号private int port = 8821;// 服务端private ServerSocket serverSocket;public MultiThreadServer0() throws IOException{// 创建服务器端serverSocket = new ServerSocket(port);System.out.println("服务器启动");}public void service(){while (true){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{try{if (socket != null){socket.close();}}catch (IOException e){e.printStackTrace();}}}}/** * 多线程服务端1 */public class MultiThreadServer1{// 端口号private int port = 8821;// 服务端private ServerSocket serverSocket;// 线程池private ExecutorService executorService;// 单个CPU线程池大小private final int POOL_SIZE = 10;public MultiThreadServer1() throws IOException{// 创建服务器端serverSocket = new ServerSocket(port);// 获取当前系统的CPU数目int cpuNums = Runtime.getRuntime().availableProcessors();// 根据系统资源情况灵活定义线程池大小executorService = Executors.newFixedThreadPool(cpuNums * POOL_SIZE);System.out.println("服务器启动");}public void service(){while (true){Socket socket = null;try{// 客户进行连接就会触发accept方法从而建立连接socket = serverSocket.accept();// 调用线程池操作executorService.execute(new Handler(socket));}catch (Exception e){e.printStackTrace();}}}public static void main(String[] args) throws IOException{new MultiThreadServer1().service();}}/** * 多线程处理类 */class Handler implements Runnable{private Socket socket;public Handler(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{try{if (socket != null){socket.close();}}catch (IOException e){e.printStackTrace();}}}}

 

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

服务器启动
客户端的IP:127.0.0.1
客户端的端口:3931
客户端的信息:我是徐越2
客户端的IP:127.0.0.1
客户端的端口:3928
客户端的信息:我是徐越1


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

原创粉丝点击