黑马程序员--网络编程

------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------

网络编程

 

      网络模型
      OSI(Open System Interconnection开放系统互连)参考模型
      TCP/IP参考模型
      网络通讯要素
      IP地址
      端口号
      传输协议

 

 

 

网络通讯要素
                     IP地址:InetAddress
                     网络中设备的标识
                     不易记忆,可用主机名
                     本地回环地址:127.0.0.1  主机名:localhost
                     端口号
                     用于标识进程的逻辑地址,不同进程的标识
                     有效端口:0~65535,其中0~1024系统使用或保留端口。
                     传输协议
                     通讯的规则
                     常见协议:TCP,UDP

TCP和UDP:
1,UDP:
             将数据及源和目的封装成数据包中,不需要建立连接
             每个数据报的大小在限制在64k内
             因无连接,是不可靠协议
             不需要建立连接,速度快
2,TCP:
              建立连接,形成传输数据的通道。
              在连接中进行大数据量传输
              通过三次握手完成连接,是可靠协议
              必须建立连接,效率会稍低

------------------------------------------------

Socket
        Socket就是为网络服务提供的一种机制。
        通信的两端都有Socket。
        网络通信其实就是Socket间的通信。
         数据在两个Socket间通过IO传输。

------------------------------------------------------------------

UDP传输
DatagramSocket与DatagramPacket
建立发送端,接收端。
建立数据包。
调用Socket的发送接收方法。
关闭Socket。
发送端与接收端是两个独立的运行程序

发送端
在发送端,要在数据包对象中明确目的地IP及端口。

DatagramSocket ds = new DatagramSocket();
byte[] by = “hello,udp”.getBytes();
DatagramPacket dp = new DatagramPacket(by,0,by.length,
			InetAddress.getByName(“127.0.0.1”),10000);
ds.send(dp);
ds.close();


接收端

在接收端,要指定监听的端口。

DatagramSocket ds = new DatagramSocket(10000);
byte[] by = new byte[1024];
DatagramPacket dp = new DatagramPacket(by,by.length);
ds.receive(dp);
String str = new String(dp.getData(),0,dp.getLength());
System.out.println(str+"--"+dp.getAddress());
ds.close();


 

整体演示:

package cn.itcast.net.p3.chat;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;

public class UDPChatTest {

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

		
		
		//1,创建接收端和发送端。
		DatagramSocket send = new DatagramSocket(1919);
		DatagramSocket rece = new DatagramSocket(10001);
		
		new Thread(new Send(send)).start();
		new Thread(new Rece(rece)).start();
	}

}

//定义发送任务。
class Send implements Runnable{
	
	private DatagramSocket ds ;
	
	
	public Send(DatagramSocket ds) {
		super();
		this.ds = ds;
	}


	public void run(){
		
		try{
			BufferedReader bufr = new BufferedReader(new InputStreamReader(System.in));
			
			String line = null;
			
			while((line=bufr.readLine())!=null){
				
				byte[] buf = line.getBytes();
				
				DatagramPacket dp = new DatagramPacket(buf,buf.length,InetAddress.getByName("192.168.1.255"),10001);
				
				ds.send(dp);
				if("over".equals(line))
					break;
			}
			ds.close();
		}
		catch(IOException e){
				
		}
		
	}
}
//定义接收任务。
class Rece implements Runnable{
	
	private DatagramSocket ds ;
	
	public Rece(DatagramSocket ds) {
		super();
		this.ds = ds;
	}

	public void run(){
		
		
		try {
			byte[] buf = new byte[1024];
			
			while(true){
				DatagramPacket dp = new DatagramPacket(buf,buf.length);
				
				ds.receive(dp);
				
				String ip = dp.getAddress().getHostAddress();
				String text = new String(dp.getData(),0,dp.getLength());
				
				System.out.println(ip+":"+text);
				if("over".equals(text)){
					System.out.println(ip+".....离开聊天室");
				}
			}
			
		} catch (Exception e) {
			// TODO: handle exception
		}
		
	}
}


 

TCP传输
Socket和ServerSocket
建立客户端和服务器端
建立连接后,通过Socket中的IO流进行数据的传输
关闭socket
同样,客户端与服务器端是两个独立的应用程序。

客户端
通过Socket建立对象并指定要连接的服务端主机以及端口。

Socket s = new Socket(“192.168.1.1”,9999);
OutputStream out = s.getOutputStream();
out.write(“hello”.getBytes());
s.close();


建立客户端:

package cn.itcast.net.p1.uploadtext;

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

public class UploadTextClient {

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

		/*
		 * 需求:读取一个本地文件,将数据发送到服务端,服务器端对数据进行存储。 
		 * 存储完毕后,给客户端一个提示。
		 * 文本文件上传。
		 */
		//1,创建客户端socket服务。
		
		Socket s = new Socket("192.168.1.100",10005);
		
		//2,读取本地文件,
		BufferedReader bufr = new BufferedReader(new FileReader("tempfile\\client.txt"));
		
		//3,确定目的:网络。
		PrintWriter out = new PrintWriter(s.getOutputStream(),true);
		
		String line = null;
		
		while((line=bufr.readLine())!=null){
			out.println(line);
		}
		
		//给服务端发送一个结束标记,使用Socket对象的shutdownOutput()方法。
		s.shutdownOutput();
		
		//给服务端发送一个自定义结束标记。后期可以使用事件毫秒值字符串。
//		out.println("over");
		
		//4,读取服务端的回馈信息。
		BufferedReader bufIn = new BufferedReader(new InputStreamReader(s.getInputStream()));
		
		String text = bufIn.readLine();
		
		System.out.println("server:"+text);
		
		bufr.close();
		s.close();
		
	}

}


服务端
建立服务端需要监听一个端口

ServerSocket ss = new ServerSocket(9999);
Socket s = ss.accept ();
InputStream in = s.getInputStream();
byte[] buf = new byte[1024];
int num = in.read(buf);
String str = new String(buf,0,num);
System.out.println(s.getInetAddress().toString()+”:”+str);
s.close();
ss.close();


 

建立服务端

package cn.itcast.net.p1.uploadtext;

import java.io.BufferedReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;

public class UploadTextServer {

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

		/*
		 * 服务端:对客户端发送的数据进行接收并存储到一个文件中。
		 * 并对客户端进行"上传成功"字样的返回。
		 */
		
		//1,创建服务器端socket服务。
		ServerSocket ss = new ServerSocket(10005);
		
		//2,获取客户端对象。
		Socket s = ss.accept();
		System.out.println(s.getInetAddress().getHostAddress()+"......connected");
		
		//3,读取客户端发来的数据。源。
		BufferedReader bufIn = new BufferedReader(new InputStreamReader(s.getInputStream()));
		
		//4,将数据写入到一个文件中。
		PrintWriter pw = new PrintWriter(new FileWriter("tempfile\\server.txt"),true);
		
		String line = null;
		while((line=bufIn.readLine())!=null){
			
//			if("over".equals(line)){
//				break;
//			}
			pw.println(line);
		}
		
		PrintWriter out = new PrintWriter(s.getOutputStream(),true);
		out.println("上传成功");
		
		pw.close();
		s.close();
		ss.close();
	}

}


 

Tcp传输最容易出现的问题
客户端连接上服务端,两端都在等待,没有任何数据传输。
通过例程分析:
因为read方法或者readLine方法是阻塞式。
解决办法:
自定义结束标记
使用shutdownInput,shutdownOutput方法

你可能感兴趣的:(黑马程序员--网络编程)