Java网络编程之TCP、UDP

       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();

	}

}







  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值