Java网络编程提供了两种协议:TCP(传输控制协议)和UDP(数据报协议)。TCP(Transmission Control Protocol)是一种可靠的传输协议,传输时会采用“三次握手”端的方式建立连接,以保证数据的可靠性和安全性;而UDP(User Datagram Protocol)协议是一种不可靠的传输协议,发送的数据不一定能够接受的到,网上的聊天是工具一般采用的此协议。下面将详细的接受TCP和UDP的使用以及相应的编码。

一、TCP网络通信
       Java中使用Socket(套接字)实现TCP。服务器端使用ServerSocket类,客户端使用Socket类实现。
     
       1、ServerSocket类
        其主要有如下的方法:
       



         

ServerSocket()   创建非绑定服务器套接字。 
  
           ServerSocket(int port)  创建绑定到特定端口的服务器套接字。 
  
          
  
           Socket accept()    侦听并接受到此套接字的连接。 
  
            void close()    关闭此套接字 
  
           boolean isClosed()   返回 ServerSocket 的关闭状态。 
  
           InetAddress getInetAddress()    返回此服务器套接字的本地地址。 
  
           void bind(SocketAddress endpoint)   将 ServerSocket 绑定到特定地址(IP 地址和端口号)。 
  
           boolean isBound()   返回 ServerSocket 的绑定状态。 
  
           SocketAddress getLocalSocketAddress()   返回此套接字绑定的端点的地址,如果尚未绑定则返回 null。


        
         服务器端每次运行是都要使用accept()方法等待客户端的连接,此方法执行之后服务器端将进入阻塞状态,知道客户端连接之后程序才继续执行,此方法返回是Socket,代表一个客户端对象。
        
       2、Socket类
       两台机器连接通信的端点。主要使用如下方法:
     
 

Socket(String host, int port)  创建一个流套接字并将其连接到指定主机上的指定端口号。 
  
       OutputStream getOutputStream()   返回此套接字的输出流。 
  
       InputStream getInputStream()    返回此套接字的输入流。 
  
       boolean isBound()    返回套接字的绑定状态。 
  
       boolean isClosed()   返回套接字的关闭状态。 
  
       boolean isConnected()     返回套接字的连接状态。 
  
       void close()     关闭此套接字。


     其通过字节流和服务端进行通信。

      实例一、下面是实现一个简单的TCP客户端可服务器端通信。
   (1)服务器端:

package andy.network.test;

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

/**  
 * @author Zhang,Tianyou  
 * version:2014-11-25 上午10:49:11  
 * 
 *  
 */

public class FirstTCPServer {

	/**
	 * @param args
	 * @throws IOException 
	 */
	public static void main(String[] args) throws IOException {
		//创建服务器
		ServerSocket server = null;
		Socket socket = null;
		PrintStream out = null;
		//服务器在9999上等待客户端的访问
		server = new ServerSocket(9999);
		
		System.out.println("服务器端已经运行,等待客户的响应。。。");
		//程序阻塞 等待客户端的访问
		socket = server.accept();
		//向客户端输出信息
		String str = "hello andy.";
		
		out = new PrintStream(socket.getOutputStream());
		out.print(str);
		out.close();
		socket.close();
		server.close();
		
	}

}



(2)客户端:


package andy.network.test;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;
import java.net.UnknownHostException;

/**
 * @author Zhang,Tianyou 
 * version:2014-11-25 上午11:02:17
 * 
 * 
 */

public class FirstTCPSocket {

	/**
	 * @param args
	 * @throws IOException
	 * @throws UnknownHostException
	 */
	public static void main(String[] args) throws UnknownHostException,
			IOException {
		// 定义客户端
		Socket client = null;
		// 设置地址和端口
		client = new Socket("localhost", 9999);

		BufferedReader buf = null; // 结束服务端流
		buf = new BufferedReader(new InputStreamReader(client.getInputStream()));
		String str = buf.readLine();
		System.out.println("服务器端通知信息:" + str);
		buf.close();
		client.close();

	}

}



   实例二


   实现客户端和服务器端的通信,服务器端可以响应多个客户端,每个客户端请求就启动一个线程。



    (1)服务端


 


package andy.network.test;

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

/**
 * @author Zhang,Tianyou 
 * version:2014-11-25 上午11:41:22
 * 
 *         聊天服务器端
 */

public class ChatServer {

	/**
	 * @param args
	 * @throws IOException
	 */
	public static void main(String[] args) throws IOException {

		ServerSocket server = null;
		Socket client = null;
		// 监听9999端口的连接
		server = new ServerSocket(9999);
		boolean  flag = true;
		while (flag) {
			System.out.println("服务器运行,等待客户端连接。");
			client = server.accept();
			// 对每一个客户端请求启动一个线程
			new Thread(new ChatThread(client)).start();

		}
		
		server.close();

	}

}



 对应服务端线程任务:


 


package andy.network.test;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.net.Socket;

/**
 * @author Zhang,Tianyou 
 * version:2014-11-25 上午11:24:26
 * 
 *         使用多线程机制,在每个用户响应之后启动一个新任务
 * 
 */

public class ChatThread implements Runnable {

	// 接受客户端
	private Socket client = null;

	public ChatThread(Socket client) {
		this.client = client;
	}

	@Override
	public void run() {
		// 向客户端发送数据
		PrintStream out = null;
		// 接收客户端发来的数据
		BufferedReader buff = null;
		try {
			// 得到客户端的输入信息
			buff = new BufferedReader(new InputStreamReader(
					client.getInputStream()));
			out = new PrintStream(client.getOutputStream());
			//标志是否一个客户端的操作完毕
			boolean flag = true;
			
			while (flag) {
				//不断的接收信息
				String str = buff.readLine();
				if(str == null || "".equals(str)){
					flag = false;//客户端操作结束
				}else{
					if("bye".equals(str)){
						flag = false;
						out.println("bye-bye"); 
					}else {
						//向客户端回显输入
						out.println("you input:" + str);
					}
				}
			}
			
			out.close();
			client.close();

		} catch (Exception e) {
			System.out.println("服务器异常!"); 
		}

	}

}



(2)客户端


package andy.network.test;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.net.Socket;
import java.net.UnknownHostException;

/**
 * @author Zhang,Tianyou 
 * version:2014-11-25 上午11:53:03
 * 
 *         聊天客户端程序
 * 
 */

public class ChatClient {

	public static void main(String[] args) throws UnknownHostException,
			IOException {

		Socket client = null;
		client = new Socket("localhost", 9999);
		// 接收服务器端的信息
		BufferedReader buff = null;
		// 向服务器端发送数据
		PrintStream out = null;
		BufferedReader input = null;
		// 获取键盘输入数据
		input = new BufferedReader(new InputStreamReader(System.in));

		out = new PrintStream(client.getOutputStream());

		buff = new BufferedReader(
				new InputStreamReader(client.getInputStream()));
		// 标志位
		boolean flag = true;
		while (flag) {
			System.out.println("输入信息:");
			String str = input.readLine();
			// 向服务器端输出信息
			out.println(str);

			if ("bye".equals(str)) {
				flag = false;
			} else {
				String chatCont = buff.readLine();
				System.out.println(chatCont);
			}

		}

		client.close();
		buff.close();
	}

}



二、UDP网络通信


   TCP的通信是建立在可靠通信的基础上,UDP则是不可靠的通信,使用数据报形式发送数据。


   在Java中主要有DatagramPacket和DatagramSocket实现。



  1、DatagramPacket主要方法


       DatagramPacket(byte[] buf, int length)


            构造 DatagramPacket,用来接收长度为 length 的数据包。


      DatagramPacket(byte[] buf, int length, InetAddress address, int port)


           构造数据报包,用来将长度为 length 的包发送到指定主机上的指定端口号。


      byte[] getData()


            返回数据缓冲区。


     int getLength()


          返回将要发送或接收到的数据的长度。



 2、DatagramSocket主要方法


     DatagramSocket(int port)


            创建数据报套接字并将其绑定到本地主机上的指定端口。


     void receive(DatagramPacket p)


            从此套接字接收数据报包。


     void send(DatagramPacket p)


            从此套接字发送数据报包。


 在使用UDP时,先使用客户端指定好要接受的数据和端口。然后开启服务端发送数据。



实现如下:


(1)客户端


package andy.network.test;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;

/**
 * @author Zhang,Tianyou 
 * version:2014-11-25 下午3:04:10
 * 
 *         UDP客户端
 */

public class UDPClient {

	/**
	 * @param args
	 * @throws IOException
	 */
	public static void main(String[] args) throws IOException {
		// 客户在9999端口监听
		DatagramSocket dSocket = null;
		dSocket = new DatagramSocket(9999);
		// 定义接收数据的字节长度
		byte[] buff = new byte[1024];
		DatagramPacket dPacket = null;
		// 指定接收数据的长度1024
		dPacket = new DatagramPacket(buff, 1024);
		System.out.println("等待接受数据。。");
		//接收数据
		dSocket.receive(dPacket);
		String str = new String(dPacket.getData(), 0, dPacket.getLength())
				+ "from" + dPacket.getAddress().getHostAddress() + ":"
				+ dPacket.getPort();
		System.out.println(str);
		//关闭数据报套接字
		dSocket.close();
	}

}



  (2)服务器端



package andy.network.test;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;

/**  
 * @author Zhang,Tianyou  
 * version:2014-11-25 下午3:13:38  
 * 
 * UDP服务器端
 *  
 */

public class UDPServer {

	/**
	 * @param args
	 * @throws IOException 
	 */
	public static void main(String[] args) throws IOException {
		DatagramSocket dSocket = null;
		//服务端在3333端口监听
		dSocket = new DatagramSocket(3333);
		DatagramPacket dPacket = null;
		//要发生的数据
		String str = "hello andy!";
		//向目标端口地址发送数据报
		dPacket = new DatagramPacket(str.getBytes(), str.length(),
				InetAddress.getByName("localhost") , 9999);
		
		System.out.println("发送数据报"); 
		
		dSocket.send(dPacket);
		dSocket.close();

	}

}