黑马程序员_java_网络编程

来源:互联网 发布:智业软件 编辑:程序博客网 时间:2024/06/05 07:20

-------android培训、java培训、期待与您交流! ----------

通信协议】分为很多种,其中传输层中常见的协议就是 TCP / UDP 协议

TCP(Transmission Control Protocol)传输控制协议;是面向连接的协议,在收发数据前,必须和对方建立可靠的连接。一个TCP连接必须要经过三次对话才能建立起来

UDP:(User Data Protocol)用户数据报协议;UDP是一个非连接的协议,传输数据之前源端和终端不建立连接

UDP和TCP的区别

UDP:
1:连接:将数据及源和目的封装成数据包中,不需要建立连接。---------面向无连接。
2:数据大小:每个数据报包的大小在限制在64k内。
3:安全性:因无连接,是不可靠的协议且传送数据不稳定,易出错。数据也就有可能收不到,不可靠
4:效率:不需要建立连接,速度快,效率高。
5,应用:主要用于视频会议聊天,一些缺少点数据无关紧要,可靠性要求低,传输经济的应用。
TCP:
1:连接:需建立连接,形成传输数据的通道。
2:数据大小:在连接中进行大数据传输。
3:安全性:通过三次握手完成连接,是可靠协议,比较安全。
4:效率:因为必须建立连接,所以效率会稍低。
5:应用:主要用于一次传输大量报文的情形,如文件传输,远程登录等;
总的来说:TCP协议提供可靠的服务,UDP协议提供高效率的服务。

网络编程其实也就是Socket 编程,Socket就是为网络服务提供的一种机制,它是通信的端点,在相互通信的程序两端都有Socket,网络通信也就是Socket间的通信,通信产生的数据就是通过Socket间的IO流进行传输的。
我们在用java语言来进行网络通信时,我们需要对象来操作三个要素:IP地址,端口,协议
IPInetAddress类,它有两个子类:Inet4Address和Inet6Address,分别代表IPV4和IPV6。它将构造函数私有化了,所以提供了静态的方法来获取本类对象:getLocalHost()获取本机IP地址InetAddress对象。
端口是应用程序的表示,
协议就是 TCP / UDP 协议
UDP的发送端:
1).建立UDP的Socket服务,如果在创建对象时没有定义端口,系统会自动分配一个未被使用的端口。
2).明确要发送的具体数据。
3).将数据封装成数据包。
4).用Socket服务和send()方法将数据包发送出去。
5).关闭Socket服务。
UDP的接收端:
1).创建Socket服务,此时必须明确一个端口,因为只有发送到这个端口的数据才能被接收处理。
2).定义一个数据包,最大64K,用于存储接收到的数据。
3).将收到的数据存储到数据包中。
4).通过数据包的方法解析数据包中的具体数据内容。
5).关闭Socket服务。
发送端(客户端)  import java.net.*;  class  UdpSend{          public static void main(String[] args)throws Exception {               // 1,建立udp的socket服务。               DatagramSocket ds = new DatagramSocket(8888);//指定发送端口,这个可以不指定,系统会随机分配。               // 2,明确要发送的具体数据。               String text = "udp传输演示 哥们来了";               byte[] buf = text.getBytes();               // 3,将数据封装成了数据包。               DatagramPacket dp = new DatagramPacket(buf,buf.length,InetAddress.getByName("10.1.31.127"),10000);               // 4,用socket服务的send方法将数据包发送出去。               ds.send(dp);               // 5,关闭资源。               ds.close();          }  }  接收端(服务器端)  import java.net.*;  class UdpRece {          public static void main(String[] args) throws Exception{                  // 1,创建udp的socket服务。                  DatagramSocket ds = new DatagramSocket(10000);//必须指定,并且和上面的端口号一样!                  // 2,定义数据包,用于存储接收到数据。先定义字节数组,数据包会把数据存储到字节数组中。                  byte[] buf = new byte[1024];                  DatagramPacket dp = new DatagramPacket(buf,buf.length);                  // 3,通过socket服务的接收方法将收到的数据存储到数据包中。                  ds.receive(dp);//该方法是阻塞式方法。                  // 4,通过数据包的方法获取数据包中的具体数据内容,比如ip,端口,数据等等。                  String ip = dp.getAddress().getHostAddress();                  int port = dp.getPort();                  String text = new String(dp.getData(),0,dp.getLength());//将字节数组中的有效部分转成字符串。                  System.out.println(ip+":"+port+"--"+text);                  // 5,关闭资源。                  ds.close();          }  }
TCP
有两个端点:客户端 和 服务端
客户端对应的对象是Socket,服务端对应的对象是ServerSocket,所以我们在使用TCP协议时,实际上就是使用这两个对象。
TCP客户端的建立:
1).建立TCP的Socket服务,明确要访问的地址和端口。
2).如果连接成功,通道也就建立,Socket流也就产生了,调用Socket流中的输入流和输出流,进行数据传输。
3).关闭Socket服务。
TCP服务端的建立:
1).创建服务端Socket服务,并监听一个端口。
2).通过accept()方法获取连接过来的客户端对象。
3).通过获取到的Socket对象中的Socket流和具体的客户端进行通讯。
4).在关闭服务时,需要先关闭客户端,再关闭服务端,服务端也可以不关。
客户端
package Udp;  import java.io.*;  import java.net.*;  public class TcpClient   {      public static void main(String[] args) throws Exception, IOException      {          //1、建立客户端Socket,确定服务器的IP地址和端口          Socket s=new Socket(InetAddress.getByName("www.baidu.com"),443);          //2、为了发送数据,我需要获取Socket中的输出流          OutputStream os=s.getOutputStream();          os.write("百度你好".getBytes());          //3、客户端接收数据,需要获取Socket中的输入流          InputStream is=s.getInputStream();          byte[] arr=new byte[is.available()];          int count=0;          count = is.read(arr);          String s1=new String(arr,0,count);          System.out.println(s1);          //4、关闭客户端          s.close();      }  }  
服务端
package Udp;  import java.io.*;  import java.net.*;  public class TcpServer   {      public static void main(String[] args) throws IOException      {          //1、建立服务器Socket明确端口号          ServerSocket ss = new ServerSocket(11000);          //2、利用服务器Socket获取接过来的客户端Socket,用accept()方法          Socket s=ss.accept();          String st=s.getInetAddress().getHostAddress();          System.out.println("连接过来的客户端IP是:"+st);          //3、要么获取输入流,要么获取输出流          OutputStream os=s.getOutputStream();          InputStream is=s.getInputStream();          byte[] arr=new byte[1024*64];          int count =0;          count=is.read(arr);          System.out.println("客户端发送过来的消息是:"+new String(arr,0,count));          os.write("客户端你好啊!".getBytes());          //4、关闭服务端          s.close();          ss.close();      }  }  
使用TCP协议完成一个客户端一个服务器。客户端从键盘输入读取一个字符串,发送到服务器。
服务器接收客户端发送的字符串,反转之后发回客户端。客户端接收并打印。
import java.net.*;import java.io.*;import java.util.*;class  Test10{public static void main(String[] args) throws IOException{Socket s = new Socket("192.168.1.102",10003);//建立客户端,指定IP和端口BufferedReader br = new BufferedReader(new InputStreamReader(System.in));String str = br.readLine();//读取键盘录入OutputStream out = s.getOutputStream();out.write(str.getBytes());//将读取的数据写入流中//.......................接收服务端返回的数据...........................................InputStream in = s.getInputStream();//接收流,用于读取服务端返回的数据byte[] buf2 = new byte[1024];//定义缓冲区int len1 = in.read(buf2);//读取数据,存入缓冲区System.out.println(new String(buf2,0,len1));//打印}}class TcpServer//服务端{public static void main(String[] args)throws Exception{ServerSocket ss = new ServerSocket(10003);//建立服务端Socket服务,并监听一个端口Socket s = ss.accept();//通过accept方法获取连接过来的客户端对象InputStream in = s.getInputStream();//获取客户端发过来的数据,使用客户端对象的读取流来读取;String ip = s.getInetAddress().getHostAddress();//读取ip并打印,用来判断是否连接成功System.out.println(ip+"connected");byte[] buf = new byte[1024];//定义缓冲区int len = in.read(buf);//将数据读入缓冲区byte[] buf1 = new byte[1024];//定义一个新的缓冲区,用于翻转字符串for (int x = len;x>0;x--){buf1[x-1]=buf[len-x];//翻转}//System.out.println(new String(buf1,0,len));OutputStream out = s.getOutputStream();//使用客户端输出流来输出out.write(buf1);//将翻转后的字节数组写入输出流}} 
服务器面对多个客户端同时访问的原理
服务端在面对多个客户端同时访问时,需要加入线程技术,因为如果服务器端是单线程的话,一个客户端连接进来以后,必须等这个连接断开,服务端才能执行到 accept() 方法,进行下次连接
所以服务器端会加入线程技术,当有客户端发起连接时,会为这个客户端新建一个线程,这样服务器端和客户端就能同时运行,不会影响下一个客户端的连接。
public class Server {public static void main(String[] args){try {//建立Socket服务ServerSocket ss = new ServerSocket(8998);    while(true){System.out.println("服务器已就绪,正在监听端口...");//获取连入Socket对象Socket s = ss.accept();//将连入的客户端Socket对象传入线程中new Thread(new ServerThread(s)).start();}} catch (IOException e) {e.printStackTrace();}}//建立服务端线程class ServerThread implements Runnable{private Socket s;//获取客户端Socket对象ServerThread(Socket s){this.s=s;}public void run(){ try {  String ip = s.getInetAddress().getHostAddress();  System.out.println(ip+"已连接");  //调用Socket输入流BufferedInputStream buin = new BufferedInputStream(s.getInputStream());//定义客户端上传的文件名int count =1;File file = new File("E:\\c\\"+ip+"("+count+").jpg");while(file.exists()){file = new File("E:\\c\\"+ip+"("+count+++").jpg");}System.out.println(file);//建立输出流,关联文件BufferedOutputStream buout = new BufferedOutputStream(new FileOutputStream(file));byte[] by = new byte[1024];int len =0;while((len=buin.read(by))!=-1){buout.write(by,0,len);buout.flush();}//向客户端反馈信息PrintWriter bw = new PrintWriter(s.getOutputStream());bw.println("文件上传成功");bw.flush();buout.close();s.close();}catch (IOException e) {e.printStackTrace();}}

0 0