zoukankan      html  css  js  c++  java
  • Java实现——Socket网络通信的机制以及实现举例

    1. 网络间的进程通信与Socket

    TCP/IP协议族中网络层的IP地址可以唯一标识网络中的主机,而传输层的协议+端口可以唯一标识主机中的应用程序(进程)。这样利用这三元组就可以标识网络的进程了,网络中的进程通信就可以利用这个标志与其它进程进行交互。

    Socket通常也称作"套接字",用于描述IP地址和端口,是一个通信链的句柄,可以用来实现不同虚拟机或不同计算机之间的通信。在Internet上的主机一般运行了多个服务软件,同时提供几种服务。每种服务都打开一个Socket,并绑定到一个端口上,不同的端口对应于不同的服务。就目前而言,几乎所有的应用程序都是采用Socket来实现网络进程之间的通信。

    Socket所支持的协议种类也不光TCP/IP一种,因此两者之间是没有必然联系的。在Java环境下,Socket编程主要是指基于TCP/IP协议的网络编程。

    本文原创,转载请注明出处:http://blog.csdn.net/seu_calvin/article/details/51996875


    2. 传输协议

    2.1 TCP

    TCP是Tranfer Control Protocol的简称,是一种面向连接的保证可靠传输的协议。通过TCP协议传输,得到的是一个顺序的无差错的数据流。发送方和接收方的成对的两个socket之间必须建立连接,需要连接时间,以便在TCP协议的基础上进行通信。


    优缺点和应用场景

    (1)可靠稳定,传递数据前,会有三次握手建立连接,面向有连接。

    (2)传递数据时,有确认、窗口(流量控制)、重传、拥塞控制。确认机制保证接收端每收到一个正确包都会回应给发送端,超时或者数据包不完整的话发送端会重传

    缺点也比较明显了:

    (1)整体来说传输慢,效率低,占用系统资源高。

    (2)传递数据前,建立连接需要耗时,传递数据时,确认、重传、拥塞等会消耗大量时间以及CPU和内存等硬件资源。

    (3)因为有确认机制、三次握手等机制,容易被人利用,实现DOS 、DDOS攻击。

    当对网络通讯质量有要求的时候,比如:整个数据要准确无误的传递给对方,这往往用于一些要求可靠的应用,比如HTTP、HTTPS、FTP等传输文件的协议,POP、SMTP等邮件传输的协议。


    TCP连接的三次握手和四次挥手机制

    为了控制本篇篇幅,关于TCP三次握手和四次挥手的知识请看这篇


    2.2 UDP

    UDP是User Datagram Protocol的简称,是一种无连接的协议,每个数据报都是一个独立的信息,包括完整的源地址或目的地址,因此无需建立发送方和接收方的连接,它在网络上以任何可能的路径传往目的地,因此能否到达目的地,到达目的地的时间以及内容的正确性、次序性都是不能被保证的。而且被传输数据报必须限定在64k以内


    优缺点和应用场景

    把TCP的缺点拿过来就成了UDP的优点,效率高了传输快了,且更安全。缺点也就是TCP的优点,即UDP不可靠不稳定、容易丢包。

    当对网络通讯质量要求不高的时候,要求网络通讯速度能尽量的快,这时就可以使用UDP。 常见使用UDP协议的应用有QQ语音视频等。


    2.3  TCP对比UDP


    这里只需要说明其中一条有无边界:

    TCP无边界指客户端分多次发送数据给服务器,若服务器的缓冲区够大,那么服务器端会在客户端发送完之后一次性接收过来,所以是无边界的;UDP有边界指客户端每发送一次,服务器端就会接收一次,也就是说发送多少次就会接收多少次,因此是有边界的。


    3. 基于Socket的Java网络编程

    3.1 利用Socket建立连接的过程
    套接字之间的连接过程分为三个步骤:服务器监听,客户端请求,连接确认。
    (1)服务器监听:服务器端套接字处于等待连接的状态,实时监控网络状态,等待客户端的连接请求。
    (2)客户端请求:指客户端的套接字提出连接请求,要连接的目标是服务器端的套接字。为此,客户端的套接字必须首先描述它要连接的服务器的套接字,指出服务器端套接字的地址和端口号,然后就向服务器端套接字提出连接请求。
    (3)连接确认:当服务器端套接字监听到或者说接收到客户端套接字的连接请求时,就响应客户端套接字的请求,建立一个新的线程,把服务器端套接字的描述发给客户端,一旦客户端确认了此描述,双方就正式建立连接。而服务器端套接字继续处于监听状态,继续接收其他客户端套接字的连接请求。


    3.2 Socket的Java实现

    	import java.io.DataInputStream;
    	import java.io.DataOutputStream;
    	import java.io.IOException;
    	import java.net.ServerSocket;
    	import java.net.Socket;
    	public class SocketManager {
    	    public static void main(String[] args) {
    	        SocketManager manager = new SocketManager();
    	        manager.doListen();
    	    }
    	
    	    public void doListen() {
    	        ServerSocket server;
    	        try {
    	            server = new ServerSocket(9991);
    	            while (true) {
    	                Socket client = server.accept();
    	                new Thread(new SSocket(client)).start();
    	            }
    	        } catch (IOException e) {
    	            e.printStackTrace();
    	        }
    	    }
    	    //服务器进程
    	    class SSocket implements Runnable {
    	        Socket client;
    	        public SSocket(Socket client) {
    	            this.client = client;
    	        }
    	
    	        public void run() {
    	            DataInputStream input;
    	            DataOutputStream output;
    	            try {
    	                input = new DataInputStream(client.getInputStream());
    	                output = new DataOutputStream(client.getOutputStream());
    	                String listMsg = input.readUTF();
    	                output.writeUTF("Send : " + listMsg + " 
     HelloVillage...");
    	                System.out.println("Recive: " + listMsg);
    	                listMsg = input.readUTF();
    	                output.writeUTF("Send Second: " + listMsg + " 
     HelloVillage...");
    	                System.out.println("Recive Second: " + listMsg);
    	            } catch (IOException e) {
    	                e.printStackTrace();
    	            }
    	        }
    	    }
    	}
    

    	import java.io.DataInputStream;
    	import java.io.DataOutputStream;
    	import java.io.IOException;
    	import java.io.OutputStream;
    	import java.net.Socket;
    	import java.net.UnknownHostException;	
    	public class SocketClient {
    	    public static void main(String[] args) {
    	        Socket socket = null;
    	        try {
    	            socket = new Socket("127.0.0.1", 9991);
    	            //向服务器端第一次发送字符串 
    	            OutputStream netOut = socket.getOutputStream();
    	            DataOutputStream doc = new DataOutputStream(netOut);
    	            DataInputStream in = new DataInputStream(socket.getInputStream());
    	            //向服务器端第二次发送字符串 
    	            doc.writeUTF("list");
    	            String res = in.readUTF();
    	            System.out.println(res);
    	            doc.writeUTF("bye");
    	            res = in.readUTF();
    	            System.out.println(res);
    	            doc.close();
    	            in.close();
    	        } catch (UnknownHostException e) {
    	            e.printStackTrace();
    	        } catch (IOException e) {
    	            e.printStackTrace();
    	        } {
    	            if (socket != null) {
    	                try {
    	                    socket.close();
    	                } catch (IOException e) {
    	                }
    	            }
    	        }
    	    }
    	}
    


  • 相关阅读:
    hdu 4339 Query 一道挺好的树状数组题(树状数组+二分思想)
    hdu 1133 Buy the Ticket(递推+精度精算)
    hdu 1267 下沙的沙子有几粒?(二维递推题)
    hdu 3397 Sequence operation(线段树的延迟标记)
    hdu 1258(dfs)
    hdu 3911 Black And White(线段树的延迟标记法)
    hdu 4148 Length of S(n) (坑爹的规律题)
    hdu 1016(一道经典的dfs)
    如何建立一棵哈夫曼树并且输出压缩码
    Codeforces Round #588 (Div. 2) E. Kamil and Making a Stream(DFS)
  • 原文地址:https://www.cnblogs.com/qitian1/p/6461599.html
Copyright © 2011-2022 走看看