TCP/UDP实例讲解

来源:互联网 发布:开发者没有网络adb调试 编辑:程序博客网 时间:2024/04/23 13:27

基于TCP/UDP的socket通讯

一、socekt是什么?

Socket是什么?(两个港口之间通过船来传输货物,而船是协议。socket就是港口)

1、是为网络服务提供的一种机制

2、通讯的两端都有Socket

3、网络通信其实就是Socket间的通信

4、数据在两个socket间通过IO传输


二、但是都知道,港口有了,但是船的类型可不一样,有的是民用、有的是军用。各有各的!所以我们经常用的是TCP协议和UDP协议,如果TCP是军用,那么UDP就是民用,从字面意思就可以明白,TCP更可靠!那么两者的区别是什么?

UDP讲解:

1、将数据及园和目的封装成数据包中,不需要建立连接(就像寄邮件一样,并不会去操心收件人是否能一定收到)!

2、每个数据报的大小限制在64K内,(加入你有2M数据,那你只能分为多个包去发)

3、因无连接,是不可靠连接(数据容易丢失,例如我们经常下载电影、音乐就是UDP、有时候就容易下载下来不能去观看,就是一部分数据丢失了)

4、不需要建立连接,所以速度快(比如我们聊天,并不知道对方在线不,只是发出去数据就好,至于聊天数据会不会丢,没人会在意,只希望聊天速度快,而不会去纠结特别安全)!

Tcp讲解:

1、建立连接,形成传输的通道(例如打电话,双方有一个人电话挂了,就不能传输数据)

2、在连接进行大数据量的传输

3、通过三次握手完成连接,是可靠协议

4、必须建立连接,效率是稍低,但是很可靠!

举个TCP三次握手的例子:

(而TCP建立连接是通过三次握手,比如张三要给李四打电话,必须保证李四本人亲自接受并确认)

第一步:张三给李四首先拨号

第二步:李四接收到拨打的通知,点击接受通话(如果不接电话,就不可能创建通话)

第三步:双方确认你在吗,并且是否是本人

这三步确认了之后,他们就可以放心的打电话了。


我们先看一下具体如何使用TCP。看下图所示!

这里写图片描述


一、那么使用TCP,客户端和服务端是如何通讯的呢

这里写图片描述


二、实现Socket通讯的4大步

这里写图片描述


三、客户端步骤

这里写图片描述


四、服务端步骤

这里写图片描述


五、实例

  • 客户端代码
import java.io.BufferedReader;import java.io.InputStream;import java.io.InputStreamReader;import java.io.OutputStream;import java.io.PrintWriter;import java.net.Socket;/* * 基于TCP的socket通讯 * 客户端 * */public class TcpClient {    public static void main(String[] args) {        try {            //1.创建客户端Socket,指定服务器地址和端口            Socket socket=new Socket("localhost", 22222);            //2.获取输出流,向服务器端发送信息            OutputStream os=socket.getOutputStream();//字节输出流            PrintWriter pw=new PrintWriter(os);//将输出流包装为打印流            pw.write("用户名:alice;密码:789");            pw.flush();            socket.shutdownOutput();//关闭输出流            //3.获取输入流,并读取服务器端的响应信息            InputStream is=socket.getInputStream();            BufferedReader br=new BufferedReader(new InputStreamReader(is));            String info=null;            while((info=br.readLine())!=null){                System.out.println("我是客户端,服务器说:"+info);            }            //4.关闭资源            br.close();            is.close();            pw.close();            os.close();            socket.close();        } catch (Exception e) {            e.printStackTrace();        }     }}
  • 服务端代码
import java.io.IOException;import java.net.InetAddress;import java.net.ServerSocket;import java.net.Socket;/* * 基于TCP的socket通讯 * 服务端 * */public class TcpServer {    public static void main(String[] args) {        //记录客户端的数量        int count=0;        try {            //第一步,创建一个服务端的socket,即ServerSocket。指定绑定的端口,并监听此端口            //请使用,1024-65535之间的端口任意一个!            ServerSocket serverSocket = new ServerSocket(22222);            //第二步,使用accept()方法监听上方的端口,等待客户端发送过来的消息,并赋值给socket对象中            Socket socket = serverSocket.accept();            //第三步,使用getInputStream()方法,获取获取的数据,这里我封装到了一个线程里面。            System.out.println("***服务器即将启动,等待客户端的连接***");            //创建一个新的线程,把我们获得的数据对象socket传递过去,进行操作            ServerThread serverThread=new ServerThread(socket);            //启动线程            serverThread.start();            count++;//统计客户端的数量            System.out.println("客户端的数量:"+count);            InetAddress address=socket.getInetAddress();            System.out.println("当前客户端的IP:"+address.getHostAddress());        } catch (Exception e) {            // TODO Auto-generated catch block            e.printStackTrace();        }    }}
  • 创建了一个线程,来处理获得和发送的数据
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;/* * 服务器线程处理类 */public class ServerThread extends Thread {    // 和本线程相关的Socket    Socket socket = null;    public ServerThread(Socket socket) {        this.socket = socket;    }    //线程执行的操作,响应客户端的请求    public void run(){        InputStream is=null;        InputStreamReader isr=null;        BufferedReader br=null;        OutputStream os=null;        PrintWriter pw=null;        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();//关闭输入流            //-----------获取输出流,响应客户端的请求-------------------------            pw = new PrintWriter(os);            pw.write("我是给客户端返回的数据,客户端我接收到你的信息了!");            pw.flush();//调用flush()方法将缓冲输出        } catch (IOException e) {            // TODO Auto-generated catch block            e.printStackTrace();        }finally{            //关闭资源            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) {                e.printStackTrace();            }        }    }}
  • 运行结果
    这里写图片描述

注意:如果想不停的给服务器发送请求,只需要在我们服务端获得数据的时候写一个死循环,不要担心真的会死掉,因为accept()没获得客户端的数据会一直阻塞。


我们最后看下UDP。UDP应用的场景也很多,比如我们的QQ、微信等交互的应用都是用的UDP。

一、如何实现UDP,客户端

这里写图片描述

二、如何实现UDP,服务端

这里写图片描述

三、我们用代码来说话

  • 客户端
import java.net.DatagramPacket;import java.io.IOException;import java.net.DatagramPacket;import java.net.DatagramSocket;import java.net.InetAddress;import java.net.SocketException;import java.net.UnknownHostException;/* * 客户端 */public class UDPClient {    public static void main(String[] args) throws IOException {        /*         * 向服务器端发送数据         */        //1.定义服务器的地址、端口号、数据        byte[] data="用户名:大熊;密码:123".getBytes();        //2.创建数据报,包含发送的数据信息,因为客户端和服务端都在我电脑上,所以可以使用"localhost"        DatagramPacket packet=new DatagramPacket(data, data.length, InetAddress.getByName("localhost"), 8800);        //3.创建DatagramSocket对象        DatagramSocket socket=new DatagramSocket();        //4.向服务器端发送数据报        socket.send(packet);        /*         * 接收服务器端响应的数据         */        //1.创建数据报,用于接收服务器端响应的数据            byte[] data2=new byte[1024];            DatagramPacket packet2=new DatagramPacket(data2, data2.length);            //2.接收服务器响应的数据            socket.receive(packet2);            //3.读取数据            String reply=new String(data2, 0, packet2.getLength());            System.out.println("我是客户端,服务器说:"+reply);    }}
  • 服务端
import java.net.DatagramPacket;import java.io.IOException;import java.net.DatagramPacket;import java.net.DatagramSocket;import java.net.InetAddress;/* * 服务器端,实现基于UDP的用户登陆 */public class UDPServer {    public static void main(String[] args) throws IOException {        /*         * 接收客户端发送的数据         */        //1.创建服务器端DatagramSocket,指定端口        DatagramSocket socket=new DatagramSocket(8800);            //2.创建数据报,用于接收客户端发送的数据            byte[] data =new byte[1024];//创建字节数组,指定接收的数据包的大小            DatagramPacket packet=new DatagramPacket(data, data.length);            //3.接收客户端发送的数据            System.out.println("****服务器端已经启动,等待客户端发送数据");            socket.receive(packet);//此方法在接收到数据报之前会一直阻塞            //4.读取数据            String info=new String(data, 0, packet.getLength());            System.out.println("我是服务器,客户端说:"+info);            /*             * 向客户端响应数据             */            //1.定义客户端的地址、端口号、数据            InetAddress address=packet.getAddress();            int port=packet.getPort();            byte[] data2="欢迎您!".getBytes();            //2.创建数据报,包含响应的数据信息            DatagramPacket packet2=new DatagramPacket(data2, data2.length, address, port);            //3.响应客户端            socket.send(packet2);    }}
  • 运行结果:
    这里写图片描述

到这里就完事了,请注意,我们使用TCP的时候,

这里写图片描述


demo:http://download.csdn.net/detail/bobo8945510/9677947

0 0