Java TCP/UDP socket

1. UDP

UDP是用户数据包协议。Java中实现UDP协议的类是DatagramPacketDatagramSocket. DatagramPacket类将数据字节填充到UDP包中,成为“数据报”。DatagramSocket类将数据报发送出去。

MulticastSocket类是DatagramSocket类的子类,用于广播和组播的客户端。

1.1 单播

单台主机与单台主机之间的通信

client.java

import java.io.IOException;  
import java.net.DatagramPacket;  
import java.net.DatagramSocket;  
import java.net.InetAddress;  
import java.net.InetSocketAddress;  
import java.net.SocketAddress;  
  
public class ClientTest  
{  
    private static final int MAXRECEIVED = 255;  
  
    public static void main(String[] args) throws IOException  
    {  
        byte[] msg = new String("connect test successfully!!!").getBytes();  
  
        DatagramSocket client = new DatagramSocket();  
  
        InetAddress inetAddr = InetAddress.getLocalHost();  
        SocketAddress socketAddr = new InetSocketAddress(inetAddr, 8888);  
  
        DatagramPacket sendPacket = new DatagramPacket(msg, msg.length,  
                socketAddr);  
  
        client.send(sendPacket);  
  
        client.close();  
    }  
}  

server.java

import java.io.IOException;  
import java.net.DatagramPacket;  
import java.net.DatagramSocket;  
import java.util.Arrays;  
 
public class ServerTest  
{  
    private static final int MAXREV = 255;  
  
    public static void main(String[] args) throws IOException  
    {  
        DatagramSocket server = new DatagramSocket(8888);  
        DatagramPacket recvPacket = new DatagramPacket(new byte[MAXREV], MAXREV);  
  
        while (true)  
        {  
            server.receive(recvPacket);  
  
            byte[] receiveMsg = Arrays.copyOfRange(recvPacket.getData(),  
                    recvPacket.getOffset(),  
                    recvPacket.getOffset() + recvPacket.getLength());  
  
            System.out.println("Handing at client "  
                    + recvPacket.getAddress().getHostName() + " ip "  
                    + recvPacket.getAddress().getHostAddress());  
  
            System.out.println("Server Receive Data:" + new String(receiveMsg));  
  
            server.send(recvPacket);  
  
        }  
  
    }  
}  

1.2 广播

单台主机与网络中所有主机的通信,代码与单播类似,只要使用广播地址255.255.255.255即可,再有就是因为会有多个客户端同时连服务端,所以客户端要用MulticastSocket

client.java

import java.io.IOException;  
import java.net.DatagramPacket;  
import java.net.DatagramSocket;  
import java.net.InetAddress;  
  
public class BroadcastSender  
{  
    public static void main(String[] args) throws IOException  
    {  
        byte[] msg = new String("connection successfully!!!").getBytes();  
        /* 
         * 在Java UDP中单播与广播的代码是相同的,要实现具有广播功能的程序只需要使用广播地址即可, 例如:这里使用了本地的广播地址 
         */  
        InetAddress inetAddr = InetAddress.getByName("255.255.255.255");  
        MulticastSocket client = new MulticastSocket();  
  
        DatagramPacket sendPack = new DatagramPacket(msg, msg.length, inetAddr,  
                8888);  
  
        client.send(sendPack);  
        System.out.println("Client send msg complete");  
        client.close();  
    }  
}

server.java

import java.io.IOException;  
import java.net.DatagramPacket;  
import java.net.DatagramSocket;  
import java.util.Arrays;  
  
public class BroadcastReceive  
{  
    public static void main(String[] args) throws IOException  
    {  
  
        DatagramPacket receive = new DatagramPacket(new byte[1024], 1024);  
        DatagramSocket server = new DatagramSocket(8888);  
  
        System.out.println("---------------------------------");  
        System.out.println("Server current start......");  
        System.out.println("---------------------------------");  
  
        while (true)  
        {  
            server.receive(receive);  
  
            byte[] recvByte = Arrays.copyOfRange(receive.getData(), 0,  
                    receive.getLength());  
  
            System.out.println("Server receive msg:" + new String(recvByte));  
        }  
  
    }  
}  

1.3 组播

只对加入组的主机广播。组播IP地址为224.0.0.0~239.255.255.255.

client.java

import java.io.IOException;  
import java.net.DatagramPacket;  
import java.net.InetAddress;  
import java.net.MulticastSocket;  
  
//客户端  
public class MulticastSender  
{  
    public static void main(String[] args) throws IOException  
    {  
        int port = 8888;  
        byte[] msg = "Connection successfully!!!".getBytes();  
  
        InetAddress inetRemoteAddr = InetAddress.getByName("224.0.0.5");  
  
        /* 
         * Java UDP组播应用程序主要通过MulticastSocket实例进行通信,它是DatagramSocket的是一个子类, 
         * 其中包含了一些额外的可以控制多播的属性. 
         *  
         * 注意: 
         *  
         * 多播数据报包实际上可以通过DatagramSocket发送,只需要简单地指定一个多播地址。 
         * 我们这里使用MulticastSocket,是因为它具有DatagramSocket没有的能力 
         */  
        MulticastSocket client = new MulticastSocket();  
  
        DatagramPacket sendPack = new DatagramPacket(msg, msg.length,  
                inetRemoteAddr, port);  
  
        client.send(sendPack);  
  
        System.out.println("Client send msg complete");  
  
        client.close();  
  
    }  
}

server.java

import java.io.IOException;  
import java.net.DatagramPacket;  
import java.net.InetAddress;  
import java.net.MulticastSocket;  
import java.util.Arrays;  
  
//服务端  
public class MulticastReceive  
{  
    public static void main(String[] args) throws IOException  
    {  
        InetAddress inetRemoteAddr = InetAddress.getByName("224.0.0.5");  
  
        DatagramPacket recvPack = new DatagramPacket(new byte[1024], 1024);  
  
        MulticastSocket server = new MulticastSocket(8888);  
  
        /* 
         * 如果是发送数据报包,可以不加入多播组; 如果是接收数据报包,必须加入多播组; 这里是接收数据报包,所以必须加入多播组; 
         */  
        server.joinGroup(inetRemoteAddr);  
  
        System.out.println("---------------------------------");  
        System.out.println("Server current start......");  
        System.out.println("---------------------------------");  
  
        while (true)  
        {  
            server.receive(recvPack);  
  
            byte[] recvByte = Arrays.copyOfRange(recvPack.getData(), 0,  
                    recvPack.getLength());  
  
            System.out.println("Server receive msg:" + new String(recvByte));  
        }  
  
    }  
}  

2. TCP

TCP通过三次握手建立连接,通过字节流发送数据。Java中基于TCP协议实现的网络通信的类是:

客户端的Socket类

服务器端的ServerSocket类

服务端用ServerSocket类建立一个socket,等待客户端连接。服务端与客户端建立连接后,用Socket类以InputStream/OutputStream的方式发送/接收数据。

client.java

package client;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.DatagramPacket;
import java.net.MulticastSocket;
import java.net.Socket;
import java.util.Arrays;
  
public class RunClientThread extends Thread 
{ 
	public static final int DATA_BUFFER_SIZE = 256;
	
	public RunClientThread()
	{
		Thread th = new Thread(this);
		th.start();
	}
	
	public void run()
        {
		// 从TCP server接收初始信息
		String host = "localhost";
		int port = 1122;
		try {
			Socket socket = new Socket(host,port);
			InputStream is = socket.getInputStream();
			BufferedReader bf = new BufferedReader(new InputStreamReader(is));
			String line;
			while((line = bf.readLine())!=null)
			{
				System.out.println(line);
			}
			bf.close();
			is.close();
			socket.close();
		} 
		catch (IOException e)
		{
			e.printStackTrace();
		}
    }
}  

server.java

package server;

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.OutputStream;
import java.net.Socket;

public class SingleServerThread extends Thread{

	Socket socket;
	OutputStream os;
	public SingleServerThread(Socket soc) { // 构造函数
		socket = soc;
	}

	public void run() { // 线程主体
		try {
			os = socket.getOutputStream();
			String line;
			BufferedReader is = new BufferedReader(new FileReader("events.properties"));
			while ((line=is.readLine())!=null) {	// 文件不到末尾
				line = line + "\n";					// 加换行符
				byte[] msg = line.getBytes();  		// 转换成字节流
		        os.write(msg);  
			}
			is.close(); // 关闭文件
			socket.close(); // 关闭Socket
		} catch (Exception e) {
			System.out.println("Error:" + e);
			// 出错,打印出错信息
		}
	}
}

Main.java

package server;

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;

public class RunServer {

	/**
	 * @param args
	 */
	public static void main(String[] args) throws IOException{
		// 创建TCP socket
		ServerSocket ss = new ServerSocket(1122);
		System.out.println("TCP server begins to work...");
		while (true)
		{
			Socket soc = ss.accept();
			System.out.println("TCP user accepted!");
			new SingleServerThread(soc).start();	// 每建立一个TCP连接,就创建一个TCP server线程
		}
	}

}

猜你喜欢

转载自blog.csdn.net/da_kao_la/article/details/80551786