Socket套接字/TCP

来源:互联网 发布:淘宝食品店开店要求 编辑:程序博客网 时间:2024/06/11 08:21


关于网络编程,就不得不提Socket套接字,下面就来讲讲对Socket的一些理解以及运用!


套接字(Socket),指的是一个程序的IP和端口号的结合。


我们可以这样理解:所谓网络通信,实际上指的是两台主机上面的两个程序之间的通信,

两个程序在进行通信(数据交换)的时候需要建立起一个“连接”,我们就可以认为这个连接就是一个网络套接字.



假设A主机的程序1要和B主机的程序2进行数据交换,

首先A主机的程序1需要通过B主机的IP找到B主机,然后再通过程序的端口号找到B主机的程序2

找到之后A主机的程序1B主机的程序2之间就建立起了一个连接(Socket),通过这个连接就可以实现两者之间的数据交换。



当A的程序1和B的程序2建立起连接(Socket)之后,不是直接通过socket进行数据交换的,

而是通过Socket里面的流进行通信的。

在Socket有两根流,一根是从A到B,另一根是从B到A的,对于同一根流,如果对于A是输出,那么对于B就是输入。

如下图:




熟悉了socket的概念之后,下面通过一个简单的实例来模拟一下socket的使用!

程序场景:A主机的程序1连接B主机程序2进行网络通信。此处B主机作为服务器![java.net.Socket]包


B主机程序2

package com.socket;import java.io.BufferedReader;import java.io.IOException;import java.io.InputStream;import java.io.InputStreamReader;import java.net.ServerSocket;import java.net.Socket;/** * 这个类对应的是B主机的程序2 * @author admin * */public class MyServer {public static void main(String[] args) {try {// 创建网络服务器,指定端口,提供给客户端连接ServerSocket server = new ServerSocket(9555);// 让服务器等待网络连接,服务器在等待网络连接的时候,处于一个等待状态// 不会往下执行,直到有客户端发送请求,服务器在接受到了请求之后才会继续往下执行Socket socket = server.accept();// 此处直到有客户端发送请求时,才会执行System.out.println("此处直到有客户端发送请求时,才会执行!!!");// 通过socket获取到它的输入流InputStream is = socket.getInputStream();InputStreamReader isr = new InputStreamReader(is);BufferedReader br = new BufferedReader(isr);// 打印客户端输入的内容String str=null;while((str=br.readLine())!=null) {System.out.println(str);}br.close();} catch (IOException e) {e.printStackTrace();}}}


注意:

accept() : 让服务器等待网络连接,服务器在等待网络连接的时候,处于一个等待状态,不会往下执行,直到有客户端发送请求,服务器在接受到了请求之后才会继续往下执行!!所以上面accept方法行下面的的代码在启动服务器[MyServer]时不会立即执行!!



A主机的程序1

package com.socket;import java.io.IOException;import java.io.OutputStream;import java.io.PrintWriter;import java.net.Socket;import java.net.UnknownHostException;/** * 这个类对应的是A主机的程序1 * @author admin * */public class MyClient {public static void main(String[] args) {try {// 通过服务器的IP和端口号创建socket请求,一旦请求成功就创建socketSocket socket = new Socket("localhost", 9555);// 因为是客户端向服务器发送消息,所以获取输出流OutputStream os = socket.getOutputStream();PrintWriter pw = new PrintWriter(os);pw.println("A主机的程序1连接B主机程序2进行网络通信----演示");// 此处记得flush()pw.flush();// 关闭流,养成习惯pw.close();} catch (UnknownHostException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}}}


上面程序当然得先启动服务器[MyServer],然后客户端[MyClient]才能通过socket正常连接!!

此处特别注意,先启动服务器客户端才能连接,否则先启动客户端的话会报错!!!为什么会这样呢,这就是典型的

TCP模式,客户端必须确定可以建立连接,需要服务器端返回可以连接(三次握手)的信号!!!!



上面的实例只是单方面的客户端向服务器发送消息,但是很多情况下是需要客户端和服务器互相发送消息的,有点像QQ的意思!!如下图:



以下为通过线程发送和接收信息,Socket持续通信的实例代码:

服务器:

package com.test;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.ServerSocket;import java.net.Socket;/** * 服务器 * @author admin * */public class TestServer {public static void main(String[] args) {try {// 创建服务器端口,给客户端提供连接ServerSocket server = new ServerSocket(9555);// 等待客户端连接Socket socket = server.accept();// 从socket获取到输出流OutputStream os = socket.getOutputStream();PrintWriter pw = new PrintWriter(os);// 从socket获取到输入流InputStream is = socket.getInputStream();BufferedReader br = new BufferedReader(new InputStreamReader(is));ReceiveMsg rm = new ReceiveMsg(br);SendMsg sm = new SendMsg(pw);// 启动线程sm.start();rm.start();} catch (IOException e) {e.printStackTrace();}}}

客户端:

package com.test;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;/** * 客户端 * @author admin * */public class TestClient {public static void main(String[] args) {try {// 连接服务器Socket socket = new Socket("localhost",9555);// 从socket获取到输入流InputStream is = socket.getInputStream();BufferedReader br = new BufferedReader(new InputStreamReader(is));// 从socket获取到输出流OutputStream os = socket.getOutputStream();PrintWriter pw = new PrintWriter(os);// 启动接收和发送两个线程ReceiveMsg rm = new ReceiveMsg(br);SendMsg sm = new SendMsg(pw);sm.start();rm.start();} catch (UnknownHostException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}}}

发送信息线程:

package com.test;import java.io.BufferedReader;import java.io.IOException;import java.io.InputStreamReader;import java.io.PrintWriter;/** * 此线程用于发送信息 * @author Admin * */public class SendMsg  extends Thread{   // 输出流   private PrintWriter pw;   public SendMsg(PrintWriter pw){   this.pw = pw;   }       // 此线程用于发送信息    public void run(){    // 输入流,从控制台读取信息BufferedReader br = new BufferedReader(new InputStreamReader(System.in));String str=null;try {// 输出信息while((str=br.readLine())!=null){             pw.println(str);             pw.flush();}// 关闭流pw.close();} catch (IOException e) {e.printStackTrace();}}}

接收信息线程:

package com.test;import java.io.BufferedReader;import java.io.IOException;/** * 此线程用于接收信息 * @author Admin * */public class ReceiveMsg extends Thread {// 输入流private BufferedReader br;public ReceiveMsg(BufferedReader br){this.br=br;}// 此线程用于接收信息public void run(){String str=null;try {// 读取信息while((str=br.readLine())!=null){System.out.println(str);}br.close();} catch (IOException e) {e.printStackTrace();}}}




文中有考虑不周到的地方,欢迎大家指正,共同进步!!!!!



以上           

                            










0 0