黑马程序员——网络编程(一)

本文深入探讨了Java网络编程的基础概念,包括OSI参考模型、TCP/IP模型、网络通讯要素、IP地址、端口号、传输协议。重点介绍了如何通过Socket实现客户端与服务器之间的通信,包括使用UDP和TCP进行数据传输的方法,以及如何通过Socket实现简单的UDP聊天应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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

●网络模型

    OSI参考模型

    TCP/IP参考模型

●网络通讯要素

    IP地址

    端口号

    传输协议

(1)找到对方IP

(2)数据要发送到对方指定的应用程序上,为了标识这些应用程序,所以给这些网络应用程序都用数字进行标识,为了方便称呼这个数字,叫做端口,逻辑端口

(3)定义通信规则,这个通讯规则称为协议,国际组织定义了通用协议TCP/IP

●IP地址

       InetAddress[] ia = InetAddress.getAllByName("www.baidu.com");

       for (InetAddress inetAddress : ia) {

           System.out.println(inetAddress.getHostName());

           System.out.println(inetAddress.getHostAddress());

       }

 

 

 

       InetAddress i = InetAddress.getLocalHost();

       System.out.println(i);

       System.out.println(i.getHostName());

       System.out.println(i.getHostAddress());

 

●端口号:

    用于标识进程的逻辑地址,不同进程的标识

    有效端口:0~65535,其中0~1024 系统使用或保留端口

●传输协议

    通讯的规则

    常见协议:TCP  UDP

    ★UDP

        将数据即源和目的封装成数据包中,不需要建立连接

        每个数据包的大小在限制在64K内

        因无连接,是不可靠协议

        不需要建立连接,速度快

    ★TCP

        建立连接,形成传输数据的通道

        在连接中进行大数据量传输

        通过三次握手完成连接,是可靠协议

        必须建立连接,效率会稍低

●Socket

    通信的两端都有Socket

    网络通信其实就是Socket间的通信

    数据在两个Socket之间通过IO传输

●UDP传输

    DsatagramSocket与DatagramPacket

    建立发送端,接收端

    建立数据包

    调用Socket的发送接收方法

    关闭Socket

    发送端与接收端是两个独立的运行程序

192.168.1.255 port   向192.168.1.x网段port端口所有机器发广播

UDP接收

           DatagramSocket ds = new DatagramSocket(9900);

           byte[] buf = new byte[1024];      

           DatagramPacket dp = new DatagramPacket(buf,buf.length);

           ds.receive(dp);

           String ip = dp.getAddress().getHostAddress();

           String data = new String(dp.getData(),0,dp.getLength());

           int port = dp.getPort();

           System.out.println("ip:"+ip);

           System.out.println("data:"+data);

           System.out.println("port:"+port);

           ds.close();

UDP发送

       DatagramSocket ds = new DatagramSocket();

       byte[] data = "udp ge menlai le".getBytes();

       DatagramPacket dp = new DatagramPacket(data,                        data.length,InetAddress.getByName("192.168.161.1"), 10000);

       ds.send(dp);

       ds.close();

 

 

UDP聊天

import java.io.IOException;

import java.net.DatagramPacket;

import java.net.DatagramSocket;

import java.net.InetAddress;

import java.net.SocketException;

import java.net.UnknownHostException;

import java.util.Scanner;

 

class ChatSend1 implements Runnable{

    privateDatagramSocket ds;

    privatebyte[] buf;

    Scannersc = new Scanner(System.in);

    publicChatSend1(DatagramSocket ds) {

        super();

        this.ds= ds;

    }

    @Override

    publicvoid run() {

        while(true){

            try{

            buf = sc.next().getBytes();

            DatagramPacketdp = newDatagramPacket(buf,buf.length,InetAddress.getByName("192.168.161.1"),10010);

            ds.send(dp);   

        }catch (UnknownHostException e) { 

            e.printStackTrace();

        }catch (IOException e) {

            e.printStackTrace();

        }

        }

    }

}

class ChatRecieve1 implements Runnable{

    privateDatagramSocket ds;

    privateDatagramPacket dp;

    private byte[] buf = new byte[1024];

    publicChatRecieve1(DatagramSocket ds) {

        super();

        this.ds= ds;

    }

    @Override

    publicvoid run() {

            dp= new DatagramPacket(buf, buf.length);

        while(true){

            try{  

            ds.receive(dp);

            Stringstring = new String(dp.getData(),0,dp.getLength());

            System.out.println(string);

        }catch (IOException e) {

            e.printStackTrace();

        }

        }  

    }

   

}

public class ChatDemo1 {

    publicstatic void main(String[] args) throws SocketException {

        DatagramSocketds= new DatagramSocket(10000);

       

        ChatSend1chatSend = new ChatSend1(ds);

        ChatRecieve1chatRecieve = new ChatRecieve1(ds);

       

        Threadthread = new Thread(chatSend);

        Threadthread2 = new Thread(chatRecieve);

       

        thread.start();

        thread2.start();

    }

}

 

UDP图形化界面 聊天

 

import java.awt.*;

import java.awt.event.*;

import java.io.IOException;

import java.net.*;

 

class FrameInit{

    public static TextArea ta;

    private Frame frame;

    private TextField tf ,tf1;

    private Button btn;

    private Button cls;

    private DatagramPacket dp;

    private DatagramSocket ds;

    private byte[] buf;

    private String msg = null;

    public FrameInit(DatagramSocket ds) {

       super();

       this.ds = ds;

       init();

    }

    public void init(){

       frame = new Frame();

       tf = new TextField(17);

       tf1 = new TextField(27);

       btn = new Button("发送");

       cls = new Button("清空");

       ta = new TextArea(25,60);

       ta.setEditable(false);

       tf.setText("192.168.161.1:8008");

       frame.setBounds(200, 200, 500, 500);

       frame.setTitle("Socket通信");

       frame.setLayout(new FlowLayout());

       frame.add(tf);

       frame.add(tf1);

       frame.add(btn);

       frame.add(cls);

       frame.add(ta);

       MyEvevt();

       frame.setVisible(true);

    }  

    public void MyEvevt(){

       frame.addWindowListener(new WindowAdapter() {

           public void windowClosing(WindowEvent e){

              System.exit(0);

           }

       });

       btn.addActionListener(new ActionListener() { 

           @Override

           public void actionPerformed(ActionEvent e) {

              try

                  if(tf1.getText().length()>0){

                     buf = tf1.getText().getBytes();

                     dp = new DatagramPacket(buf, buf.length,InetAddress.getByName(tf.getText().split(":")[0]),Integer.parseInt(tf.getText().split(":")[1]));

                     ds.send(dp);

                     ta.append("发送:\r\n"+tf1.getText()+"\r\n");

                  }else{

                     ta.setText("发送内容不能为空!"+"\r\n");

                  }

              } catch (Exception e1) {

                  // TODO Auto-generatedcatch block

                  e1.printStackTrace();

              }

           }

       });

       cls.addActionListener(new ActionListener() {    

           @Override

           public void actionPerformed(ActionEvent e) {

              ta.setText("");     

           }

       });

    }

}

public class SocketFrame {

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

       DatagramSocket ds = new DatagramSocket(11000);

       FrameInit frameInit = new FrameInit(ds);

       byte[] b = new byte[1024];

       while(true){

           DatagramPacket dp = new DatagramPacket(b, b.length);

           ds.receive(dp);

           String string = new String(dp.getData(),0,dp.getLength());

           FrameInit.ta.append("接收:");

           FrameInit.ta.append(string+"\r\n");

          

       }

    }

}

●TCP传输

    Socket和ServerSocket

    建立客户端和服务器端

    建立连接后,通过Socket中的IO流进行数据的传输

    关闭Socket

同样,客户端与服务器端是两个独立的应用程序

因为tcp是面向连接的,所以在建立socket服务时,就要有服务端存在,并连接成功,形成通路后,在该通道进行数据的传输

 

class TCPClient{

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

       Socket s = new Socket("192.168.161.1",11000);

       OutputStream os = s.getOutputStream();

       os.write("tcp ge menlai le".getBytes());

       s.close();

    }

}

/*服务端:

 * 1.建立服务端的socket服务,并监听一个端口

 * 2.获取连接过来的客户端对象,通过ServerSocketaccept方法,所以这个方法时阻塞式的

 * 3.客户端如果发过来数据,那么服务端要使用对应的客户端对象,并获取到该客户端对象的读取流来读取发过来的数据

 *

 *

 * */

class TCPServer{

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

       ServerSocket ss = new ServerSocket();

       Socket s = ss.accept();

       InputStream is = s.getInputStream();

       byte[] buf = new byte[1024];

       int len=0;

       len = is.read(buf);

       String string = new String(buf,0,len);

       System.out.println(string);

    }

}

 

 

 

 

 

●TCP客户端和服务端不带缓冲区

import java.io.IOException;

import java.io.InputStream;

import java.io.OutputStream;

import java.net.InetAddress;

import java.net.ServerSocket;

import java.net.Socket;

 

class TCPtextServer {

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

       ServerSocket ss =new ServerSocket(10010);

       Socket accept = ss.accept();

       InputStream is = accept.getInputStream();

       byte[] buf = new byte[1024];

       int len = is.read(buf);

       String string = new String(buf,0,len);

       System.out.println(string);

       OutputStream os = accept.getOutputStream();

       os.write(string.toUpperCase().getBytes());

       accept.close();

    }

}

class TCPtextClient {

    public static void main(String[] args) throws Exception {

       Socket s = new Socket(InetAddress.getLocalHost(), 10010);

       OutputStream os = s.getOutputStream();

       os.write("tcp serveri am coming!-----Client".getBytes());

       InputStream is = s.getInputStream();

       byte[] buf = new byte[1024];

       int len = is.read(buf);

       String string = new String(buf,0,len);

       System.out.println(string);

       s.close();

    }

}

●TCP客户端和服务端带缓冲区

 public class TCPClientBuffer {

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

       Socket s = new Socket(InetAddress.getLocalHost(),10010);

       BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));

       BufferedReader brin = new BufferedReader(new InputStreamReader(System.in));

       BufferedReader bs = new BufferedReader(new InputStreamReader(s.getInputStream()));

   

       String line = null;

       while((line=brin.readLine())!=null){     

           if("over".equals(line))

              break;

           System.out.println(line);

           bw.write(line);

           bw.newLine();

           bw.flush();

           line=bs.readLine();

           System.out.println("Server:"+line);

           }

       s.close();

       brin.close();

    }

}

 

public class TCPServerBuffer {

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

       ServerSocket ss = new ServerSocket(10010);

       Socket s = ss.accept();

       System.out.println("Client:-----connection");

       BufferedReader br = new BufferedReader(new InputStreamReader(s.getInputStream()));

       //BufferedWriter bw =new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));

       PrintWriter pw = new PrintWriter(s.getOutputStream(),true);

       String line = null;

       while((line=br.readLine())!=null){

           System.out.println("Client"+line);

           /*bw.write(line.toUpperCase());

           bw.newLine();

           bw.flush();*/

           pw.println(line);

       }

       s.close();

       ss.close();

    }

}

●使用BufferedReader注意换行!!!!!!!!!!!!!!!!!!!!!!!

因为客户端和服务端都有阻塞式方法,这些方法没有读到结束标记,那么就一直等,而导致两端都在的等待

 

 

 

●TCP发送文件

客户端先发送结束标记给服务端

服务端在上传完成之后 返回 上传成功

此例为字节流传输

也可用字符流 或者 PrintWriter

结束标记用时间做标记 System.currentTimeMillis()

shutdownOutput()

 

public class TCPClientBuffer {

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

       Socket s = new Socket(InetAddress.getLocalHost(),10010);

      

       BufferedOutputStream bos = new BufferedOutputStream(s.getOutputStream());

       BufferedInputStream bis = new BufferedInputStream(new FileInputStream("g:/tupian.jpg"));

      

       byte[] buf = new byte[1024];

       int len = 0;

       while((len = bis.read(buf))!=-1){

           bos.write(buf,0,len);

           bos.flush();

       }

       bis.close();

       s.close();

    }

}

 

 

public class TCPServerBuffer {

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

       ServerSocket ss = new ServerSocket(10010);

       Socket s = ss.accept();

       System.out.println("Client:-----connection");

      

       BufferedInputStream bis = new BufferedInputStream(s.getInputStream());

       BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("g:/socket.jgp"));

       int len = 0;

       byte[] buf = new byte[1024];

       while((len = bis.read(buf))!=-1){

           bos.write(buf, 0, len);

           bos.flush();

       }

       s.close();

       ss.close();

       bos.close();

    }

}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值