java网络编程总结

最近在研究kafka的源码,先说一下感触,虽然kafka不是用java写的,只是提供了java的客户端,但是单纯这个客户端的代码已经让我焦头烂额了,可以很肯定的说现在的我真的是太菜了,需要学习的东西太多,不过乐观点的说我的成长空间也很大,而且读源码真的是非常好的学习机会,很推荐有时间的朋友们读一个框架的源码。通过读源码我发现了很多的不足,这里仅仅记录一些关于java网络编程的,顺便将以前总结的关于网络编程的笔记汇总一下。关于kafka的源码中的补充的知识也会逐渐添加进来。

1、InetAddress类,这个出现于kafkaProducer的源码中。这个类表示的是ip地址的详细信息,通过它既可以获得域名也可以获得ip地址,但是这个类是不含有端口号的。

     InetAddress没有构造方法,只能通过类中的静态方法获得实例,既可以通过getBy***方法获得指定域名的ip也可以通过getLocalhost来获得本机的ip。

2、InetSocketAddress类,这个是在对InetAddress类的补充,在ip地址的基础上添加了端口号。

    InetSocketAddress的构造方法很简单,既可以使用域名+端口号,也可以使用InetAddress + 端口号。

数据的传输:TCP(transfer control protocal,传输控制协议)  UDP(user datagram protocal)

    TCP是面向连接的传输,必须要建立起连接之后才可以进行通信。tcp的连接的建立需要三次握手,先是客户端发送SYN同步报文,然后服务器端发送ACK确认报文即SYN同步报文,最后客户端再次发送ACK确认报文连接即建立。tcp就像是打电话,通话双方都必须拿起电话才可以讲话。tcp的这个特性决定了他的安全性,消息不会丢失,但是效率去相对较低。

    UDP一种无连接的传输层协议,提供面向事物的简单不可靠信息传送服务。他是非面向连接的,即不用连接也能通信,所以存在传输不可靠的特点,就像是发送短信,即使另一方没有开机也可以发,而且发送方无法得知是否已经发送。

    在java的网络编程中,UDP使用的是DatagramSocket + DatagramPacket,DatagramSocket是用来发送和接收DataGramPacket(数据报)的对象,服务器端和客户端都使用的是DatagramSocket,DatagramPacket就是数据报,里面含有要发送的信息和此数据报要发送到的目的地的ip地址和端口号,在服务器端和客户端的数据报的建立方法不同。     TCP使用的是:ServerSocket + Socket,ServerSocket是用来监听访问的,每当有新的请求来时服务器端就会建立socket用来和此进行会话。

UDP的编程实例:

//这是服务器端的代码
public class UDPServer {

	public static void main(String[] args) throws IOException {
	    DatagramSocket server = new DatagramSocket(9999);
	    byte[] container = new byte[1024];
	    //这个是用来接受数据的信息报
	    DatagramPacket pack = new DatagramPacket(container, container.length);
		  
	    server.receive(pack);//程序执行到这的时候就会阻塞
	     
	    byte[] data = pack.getData();
	    String dataStr  = new String(data, 0, pack.getLength());
	    System.out.println(dataStr);
	    server.close(); 
		
	}
}
//这是客户端的代码
public class UDPClient {

	public static void main(String[] args) throws IOException {
		DatagramSocket cli = new DatagramSocket(8888);
		byte[] data = "hello world".getBytes();
		
		//这个是用来发送的信息报的,所以必须指定此数据报的发送的ip和端口
		DatagramPacket packet = new DatagramPacket(data, data.length,
				new InetSocketAddress("localhost", 9999));
		cli.send(packet);;
		cli.close(); 
	}
}
 可以在不运行服务器端的情况下运行客户端,并且不会报错,因为UDP不是面向连接的,所以不用建立连接,不过这样也就会丢失数据报。所以如果要看到实验的结果必须要先运行服务器端(服务器端在执行到receive时就会阻塞),然后再运行客户端。

除了发送字符串类之外,也可以发送java类,先用ObjectOutputStream将java类转换为byte[],然后发送byte[],再接收端用ObjectInputStream将接受到的byte[]转化为指定的java类。

public class UDPServer {

	public static void main(String[] args) throws IOException, ClassNotFoundException {
		DatagramSocket server = new DatagramSocket(9999);
		byte[] container = new byte[1024];
		//这个是用来接受数据的信息报
		DatagramPacket pack = new DatagramPacket(container, container.length);
		  
	    server.receive(pack);
	     
	    byte[] data = pack.getData();
	    ByteArrayInputStream stream = new ByteArrayInputStream(data, 0, pack.getLength());
	    ObjectInputStream in = new ObjectInputStream(stream);
	    UDPClient c = (UDPClient) in.readObject(); 	   
	    System.out.println(c.name);
	    server.close(); 
		
	}
}
public class UDPClient implements Serializable { 
	 
	private static final long serialVersionUID = 5810472933704265330L;
	public String name = "hello world"; 
	
	public static void main(String[] args) throws IOException {
		DatagramSocket cli = new DatagramSocket(8888);
		UDPClient c = new UDPClient();
		ByteArrayOutputStream stream  = new ByteArrayOutputStream();
		ObjectOutputStream out = new ObjectOutputStream(stream);
		out.writeObject(c);		
		byte[] data = stream.toByteArray();
		
		//这个是用来发送的信息报的,所以必须指定此数据报的发送的ip和端口
		DatagramPacket packet = new DatagramPacket(data, data.length,
				new InetSocketAddress("localhost", 9999));
		cli.send(packet);;
		cli.close(); 
	}
}

 TCP编程实例

   服务器端:

public class Server {

	public static void main(String[] args) throws IOException {
		ServerSocket server = new ServerSocket(9999);
		
		while(true){
			Socket socket =  server.accept();//
			System.out.println("有请求来了");
			new Thread(new SocketTask(socket)).start();
		}
	}
}
class SocketTask implements Runnable{
	Socket socket =  null;
	public SocketTask(Socket socket) {
		if(socket == null){
			throw new IllegalArgumentException();
		}
	    this.socket = socket;
	}
	
	public void run() {
		try {
			 InputStream inputStream = socket.getInputStream();
			 BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream, "UTF-8"));
			 String msg = reader.readLine();
			 System.out.println(msg);
			 socket.close();
		} catch (Exception e) {
			e.printStackTrace();
		} 
	}
}

 说明:ServerSocket的accept方法会阻塞,这里采用的办法是无限循环,只要有一个请求来了就会建立一个线程去处理这个这次请求,将返回的socket实例加入到这个线程中去。

客户端:

public class Client { 
	public static void main(String[] args) throws IOException {
		Socket socket = new Socket("localhost",9999);
		OutputStream outStream = socket.getOutputStream();
		BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(outStream,"UTF-8"));
		writer.write("中国");
 		writer.close();
		socket.close();	 
	}
}

在TCP中,如果先启动客户端的话就会报错,因为TCP是面向连接的,必须现有连接才可以进行通信,而UDP则相反。如果想得到预期的效果就必须先启动服务器端。

 这几个小例子都很简单,最初学java的时候经常写,重新写一遍的原因就是复习一下,做到温故知新,熟能生巧。

相关推荐