zoukankan      html  css  js  c++  java
  • Java Socket编程(二)Socket基础


    二、Socket基础

    1.地址的获得
    	public static void main(String[] args) {
    
    		try {
    			Enumeration<NetworkInterface> interfaces = NetworkInterface.getNetworkInterfaces();
    			while (interfaces.hasMoreElements()) {
    				NetworkInterface iface = interfaces.nextElement();
    				System.out.println("Interface: " + iface.getName());
    				
    				Enumeration<InetAddress> addrList = iface.getInetAddresses();
    				if (!addrList.hasMoreElements())
    					System.out.println("No address");
    				
    				while (addrList.hasMoreElements()) {
    					InetAddress address = addrList.nextElement();
    					System.out.println("Address: " + address.getHostAddress());
    				}
    			}
    			
    		} catch (SocketException e) {
    			e.printStackTrace();
    		}
    		
    	}

    2.TCP实例程序

    要注意一点,虽然在Client端只用了一个write()方法发送字符串,服务器端也可能从
    多个块中接受该信息。即使回馈字符串在服务器返回时存于一个块中,也可能被TCP
    协议分割成多个部分。

    TCPEchoClientTest.java
    	public static void main(String[] args) throws IOException {
    
    		String server = args[0];
    		byte[] data = args[1].getBytes();
    		int port = 7;
    		
    		Socket socket = new Socket(server, port);
    		System.out.println("Connected to server...");
    		
    		InputStream in = socket.getInputStream();
    		OutputStream out = socket.getOutputStream();
    		
    		out.write(data);
    		
    		int totalBytesRcvd = 0;
    		int bytesRcvd;
    		while (totalBytesRcvd < data.length) {
    			if ((bytesRcvd = in.read(data, totalBytesRcvd, 
    					data.length - totalBytesRcvd)) == -1)
    				throw new SocketException("Connection closed");
    			totalBytesRcvd += bytesRcvd;
    		}
    		
    		System.out.println("Received: " + new String(data));
    		
    		socket.close();
    	}

    TCPEchoServerTest.java
    	private static final int BUFSIZE = 32;
    	
    	public static void main(String[] args) throws IOException {
    
    		ServerSocket serverSocket = new ServerSocket(7);
    		
    		int recvMsgSize;
    		byte[] receiveBuf = new byte[BUFSIZE];
    		while (true) {
    			Socket socket = serverSocket.accept();
    			System.out.println("Handling client " +
    					" from remote " + socket.getRemoteSocketAddress() + 
    					" at local " + socket.getLocalSocketAddress());
    			
    			InputStream in = socket.getInputStream();
    			OutputStream out = socket.getOutputStream();
    			
    			while ((recvMsgSize = in.read(receiveBuf)) != -1) {
    				out.write(receiveBuf, 0, recvMsgSize);
    			}
    			socket.close();
    		}
    		
    	}
    注意new Socket时指定的是远端服务器监听的端口号而没有指定本地端口,因此将
    采用默认地址和可用的端口号。在我的机器上Client端口是4593,连接到服务器的
    端口7。


    3.UDP实例程序

    为什么使用UDP协议?如果应用程序只交换少量的数据,TCP连接的建立阶段就至少
    要传输其两倍的信息量(还有两倍的往返时间)。

    UDPEchoClientTest.java
    	public static void main(String[] args) throws IOException {
    
    		InetAddress serverAddress = InetAddress.getByName(args[0]);
    		byte[] bytesToSend = args[1].getBytes();
    		
    		DatagramSocket socket = new DatagramSocket();
    		socket.setSoTimeout(3000);
    		
    		DatagramPacket sendPacket = new DatagramPacket(
    			bytesToSend, bytesToSend.length, serverAddress, 7);
    		
    		DatagramPacket receivePacket = new DatagramPacket(
    			new byte[bytesToSend.length], bytesToSend.length);
    		
    		// Packets may be lost, so we have to keep trying
    		int tries = 0;
    		boolean receivedResponse = false;
    		do {
    			socket.send(sendPacket);
    			try {
    				socket.receive(receivePacket);
    				if (!receivePacket.getAddress().equals(serverAddress))
    					throw new IOException("Receive from unknown source");
    				receivedResponse = true;
    			} 
    			catch (IOException e) {
    				tries++;
    				System.out.println("Timeout, try again");
    			}
    		} while (!receivedResponse && tries < 5);
    		
    		if (receivedResponse)
    			System.out.println("Received: " + new String(receivePacket.getData()));
    		else
    			System.out.println("No response");
    		
    		socket.close();
    	}

    UDPEchoServerTest.java
    	private static final int ECHOMAX = 255; 
    	
    	public static void main(String[] args) throws IOException {
    
    		DatagramSocket socket = new DatagramSocket(7);
    		DatagramPacket packet = new DatagramPacket(new byte[ECHOMAX], ECHOMAX);
    		
    		while (true) {
    			socket.receive(packet);
    			System.out.println("Handling client at " + packet.getAddress());
    			
    			socket.send(packet);
    			packet.setLength(ECHOMAX);
    		}
    		
    	}
    通过这个例子与之前TCP的实例进行比较,有如下区别:

    A.DatagramSocket在创建时不需要指定目的地址,因为UDP不需要建立连接,每个
    数据报文都可以发送或接收于不同的目的地址。

    B.如果像TCP一样在read()上阻塞等待,将可能永远阻塞在那里,因为UDP协议只是
    简单地扩展了IP协议,UDP报文可能丢失掉。所以一定要设置阻塞等待的超时时间。

    C.UDP协议保留了消息的边界信息,每次receive()调用最多只能接收一次send()方法
    调用所发送的数据。

    D.一个UDP报文DatagramPacket能传输的最大数据是65507字节,超出部分的字节将
    自动被丢弃,而且对接收程序也没有任何的提示。因此缓存数组可以设置成65000字节
    左右是安全的。

    E.如果反复使用同一个DatagramPacket实例调用receive()方法,每次调用前都必须显式
    地将消息的内部长度重置为缓存区的实际长度。

  • 相关阅读:
    定义通用类型,便于移植和32位、64位的编译
    映射密码的加密,解密以及暴力破解
    位移密码的加密,解密以及暴力破解
    TCP三次握手和四次挥手通俗理解
    git常用命令
    pip及npm换源
    win10安装Docker并换国内源
    搜索引擎工作原理
    wsgi_uwsgi_nginx理论知识
    课程全文检索接口
  • 原文地址:https://www.cnblogs.com/xiaomaohai/p/6157827.html
Copyright © 2011-2022 走看看