十三.Java基础_网络编程

来源:互联网 发布:js获取input上传文件 编辑:程序博客网 时间:2024/04/29 01:34

Java基础_网络编程


.UDPTCP传输各自的特点

UDP的特点:将数据及源和目的封装在大小限制在64K内的数据包中,不需要建立连接,速度快,也因此是不可靠协议。

TCP的特点:需要建立连接形成传输数据的同道,在连接中进行大数据量传输,因为必须建立连接,导致效率会稍低,但通过三次握手完成连接,是可靠协议。

.Socket

网络编程其实就是Socket编程:

Socket就是为网络服务提供的一种机制,网络通信其实就是Socket间的通信,通信的两端都有Socket,数据在两个Socket间通过IO传输,毕老师形象的将其比喻为码头,要先建立两地的码头才能进行互相输送数据,编程时要先建立Socket服务。

.IP地址及端口

IP 地址是 IP 使用的 32 位或 128 位无符号数字,它是一种低级协议,UDP 和 TCP 协议都是在它的基础上构建的IP地址是网络中设备的标识,本地IP地址为:127.0.0.1,主机名为:localHost

端口用于标识进程的逻辑地址,就是不同进程的标识,有效端口:0~65535,其中0~1024为系统使用或保留端口。

一些重要的方法:

InetAddress.getLocalHost();返回本地主机

InetAddress.getByName(String host):通过主机名字获取主机的IP地址

InetAddress.getHostAddress(); 返回IP地址字符串

InetAddress.getHostName().返回此IP地址的主机名

.应用实例

UDP协议传输:

1)要求:用UDP协议从一台主机发送一串数据”Hello java!”到另外一台主机

思路: 

发送端:1.建立UDP Socket服务

 2.提供数据并封装到数据包中

 3.通过Socket服务发送数据

 4.关闭资源

 接收端:1.建立UDP Socket服务

 2.建立用于接收数据的数据包,用数据包接收数据是因为数据包中有更  多的处理接收到的数据的功能;

 3.通过Socket 服务的receive功能将接收的数据存入数据包中

 4.关闭资源

下面是代码:

  import java.net.*;  class UDPsend   {  public static void main(String[] args) throws Exception  {  //建立UDP Socket服务  DatagramSocket ds = new DatagramSocket(12345);  byte[] buf = "Hello java!".getBytes();  //建立数据包封装发送的数据,new DategramPacket(byte[] buf,int length,InetAddress address,int port);  DatagramPacket dp = new DatagramPacket(buf,buf.length,InetAddress.getByName("aisl-PC"),10000);  //通过Socket的功能发送数据  ds.send(dp);  //关闭资源  ds.close();  }  }    class UDPreceive   {  public static void main(String[] args) throws Exception  {  DatagramSocket ds = new DatagramSocket(10000);  byte[] buf = new byte[1024];  //建立数据包用来接收数据  DatagramPacket dp = new DatagramPacket(buf,buf.length);  //通过Socket的功能接收数据  ds.receive(dp);  //利用数据包的功能获取数据的一些信息  String ip = dp.getAddress().getHostAddress();  int port = dp.getPort();  String data = new String(dp.getData(),0,dp.getLength());  System.out.println(ip+"--"+data+"--"+port);  ds.close();  }  }

2)要求:用UDP协议实现两台主机类似QQDOS版聊天,

思路:1.要让两台主机的软件上都有接收和发送功能,那么就要让这个程序同     时具有接收和发送功能;

  2.要实现同时具有接收和发送功能就要考虑用多线程。

  import java.io.*;  import java.net.*;  class UDPliaotian  {  public static void main(String[] args) throws Exception  {  //先定义发送端和接收端Socket服务  DatagramSocket ds = new DatagramSocket();  DatagramSocket ds1 = new DatagramSocket(10001);  //开启线程  new Thread(new send(ds)).start();  new Thread(new receive(ds1)).start();  }  }  //发送端  class send implements Runnable  {  private DatagramSocket ds;  //构造函数接收一个DatatramSocket  send(DatagramSocket ds)  {  this.ds=ds;  }  //覆盖父类中的run方法  public void run()  {  try  {  //定义一个IO读取流读取键盘录入  BufferedReader bfr = new BufferedReader(  new InputStreamReader(System.in));  String line = null;  while ((line = bfr.readLine())!=null)  {  if ("88".equals(line))  break;  byte[] buf = line.getBytes();  //建立数据包封装发送的数据,new DategramPacket(byte[] buf,int length,InetAddress address,int port);  DatagramPacket dp = new DatagramPacket(  buf,buf.length,InetAddress.getByName("127.0.0.255"),10001);  //发送数据  ds.send(dp);  }  }  catch (Exception e)  {  throw new RuntimeException("发送端失败");  }  }  }  //接收端  class receive implements Runnable  {  private DatagramSocket ds;  //构造函数接收一个DatagramSocket  receive(DatagramSocket ds)  {  this.ds=ds;  }  //覆盖父类中的run方法  public void run()  {  try  {  //不断的接收数据  while (true)  {  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());  System.out.println(ip+"::"+data);  }  }  catch (Exception e)  {  throw new RuntimeException("接收端失败");  }  }  }

TCP协议传输

1)要求:让客户端连接服务端,并向服务端发送一段文字,服务端在接收到客 户端发送的文字后向客户端返回一段文字。

 思路:

 客户端:1.创建Socket服务,并指定要连接的主机和端口

 2.获取Socket流中的输出流,将数据写到该流中,通过网络发送给服务端;

 3.获取Socket流中的输入流,将服务端反馈的数据获取到,并打印

 4.关闭客户端资源

服务端:1.创建ServerSocket服务,获取客户端Socket

2.获取Socket读取流读取客户端发送的数据并打印

3.获取Socket输出流像客户端返回一句话给客户端

4.关闭资源

  import java.io.*;  import java.net.*;  class  tcpclient  {  public static void main(String[] args) throws Exception  {  //创建Socket服务,并指定要连接的主机和端口  Socket s = new Socket("127.0.0.1",10003);  //定义Socket输出流,发送一句话到服务端  OutputStream out = s.getOutputStream();  out.write("服务端你好!我是客户端!".getBytes());  /*  InputStream in = s.getInputStream();    byte[] buf = new byte[1024];  int len = in.read(buf);  System.out.println(new String (buf,0,len));  */  //获取Socket流中的输入流,将服务端反馈的数据获取到,并打印(也可用注释部分代码实现)  BufferedReader bfrin = new BufferedReader(new InputStreamReader(s.getInputStream()));  String str = bfrin.readLine();  System.out.println(str);  s.close();  }  }  class tcpserve  {  public static void main(String[] args) throws Exception  {  ServerSocket ss = new ServerSocket(10003);  Socket s = ss.accept();  String ip = s.getInetAddress().getHostAddress();  System.out.println(ip+"...connection");  //获取Socket读取流读取客户端发送的数据  InputStream in = s.getInputStream();    byte[] buf = new byte[1024];  int len = in.read(buf);  System.out.println(new String(buf,0,len));    //OutputStream out = s.getOutputStream();  //获取Socket输出流像客户端返回一句话给客户端,(也可用注释部分代码实现)  PrintWriter out = new PrintWriter(s.getOutputStream(),true);  Thread.sleep(2000);  //out.write("收到,我是服务端".getBytes());  out.println("收到,我是服务端");  s.close();  ss.close();  }}

2)要求:建立一个文本转换服务器

客户端给服务端发送文本,服务端会将文本转换成大写再返回给客户端

而且客户端可以不断的进行文本转换,当客户端输入over时,转换结束

思路:

客户端:1.建立Socket服务

2.定义IO读取流获取键盘录入

3.定义Socket输出流将键盘录入的数据发送给服务端

4.定义Socket读取流获取服务端返回大写数据并打印

5.关闭资源

服务端:1.确定源为Socket读取流,目的为Socket输出流

2.建立ServerSocket服务,接收客户端Socket

3.定义Socket读取流获取客户端发送来的数据

4.定义Socket输出流将处理后的数据发送回客户端

5.关闭资源

  import java.io.*;  import java.net.*;  class  tcpclient  {  public static void main(String[] args) throws Exception  {  Socket s = new Socket("127.0.0.1",10005);    //定义读取流读取键盘录入  BufferedReader bfr =   new BufferedReader(new InputStreamReader(System.in));    //定义Socket输出流,  BufferedWriter bfwout =   new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));     //定义Socket读取流读取服务端返回的数据  BufferedReader bfrin =   new BufferedReader(new InputStreamReader(s.getInputStream()));    String line = null;  while ((line = bfr.readLine())!=null)  {  if ("over".equals(line))  break;  bfwout.write(line);  bfwout.newLine();  bfwout.flush();    String str = bfrin.readLine();  System.out.println("server:"+str);  }  bfr.close();  s.close();  }  }  /*  服务端:  源:socket读取流  目的:socket输出流  都是文本,可装饰  */  class tcpserve  {  public static void main(String[] args) throws Exception  {  ServerSocket ss = new ServerSocket(10005);  Socket s = ss.accept();    String ip = s.getInetAddress().getHostAddress();  System.out.println(ip+"....已连接");  //定义Socket读取流用来获取客户端发送来的数据  BufferedReader bfrin =   new BufferedReader(new InputStreamReader(s.getInputStream()));  //定义Socket输出流用来将处理后的数据发送回客户端  BufferedWriter bfwout =   new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));    String line = null;  while ((line = bfrin.readLine())!=null)  {  //转换成大写并发送  bfwout.write(line.toUpperCase());  bfwout.newLine();  bfwout.flush();  }  s.close();  ss.close();  }}

3)要求:客户端向服务端上传文件

客户端向服务端发送一个文件,服务端接收文件并保存。

这里是上传一个文本文件,如果不是纯文本文件,那么程序里要使用字节流读写

  import java.io.*;  import java.net.*;  class  tcpclient  {  public static void main(String[] args) throws Exception  {  Socket s = new Socket("127.0.0.1",10006);    BufferedReader bfr =   new BufferedReader(new FileReader("Demo.java"));    PrintWriter out = new PrintWriter(s.getOutputStream(),true);    String line = null;  while ((line=bfr.readLine())!=null)  {  out.println(line);  }  s.shutdownOutput();//关闭客户端输出流,相当于给流中加入一个结束标记-1       BufferedReader bfrin =   new BufferedReader(new InputStreamReader(s.getInputStream()));    String str = bfrin.readLine();  System.out.println(str);  bfr.close();  s.close();  }  }  class tcpserver  {  public static void main(String[] args) throws Exception  {  ServerSocket ss = new ServerSocket(10006);  Socket s = ss.accept();  String ip = s.getInetAddress().getHostAddress();  System.out.println(ip+"...连接成功");    BufferedReader bfrin =   new BufferedReader(new InputStreamReader(s.getInputStream()));    PrintWriter pw = new PrintWriter(new FileWriter("server.txt"),true);    String line = null;  while ((line=bfrin.readLine())!=null)  {  pw.println(line);  }  PrintWriter out = new PrintWriter(s.getOutputStream(),true);  out.println("上传成功");    pw.close();  s.close();  ss.close();  }  }

注意:这里面有一个重要的方法,shutdownOutput():禁用此套接字的输出流,也就是关闭客户端输出流,相当于给流中加入一个结束标记,如果程序中没有实现这个步骤,那么程序运行结果为:客户端在将文件上传完成后,服务端和客户端都为无限等待状态,程序不结束。

4)要求:客户端向服务端上传一个图片

程序中要用字节流进行文件的读写

  import java.io.*;  import java.net.*;  class tcpclient   {  public static void main(String[] args) throws Exception  {  Socket s = new Socket("127.0.0.1",10007);    FileInputStream fis = new FileInputStream("1.jpg");    OutputStream out = s.getOutputStream();    int len = 0;  byte[] buf = new byte[1024];  while ((len=fis.read(buf))!=-1)  {  out.write(buf,0,len);  }  s.shutdownOutput();    BufferedReader bfrin =   new BufferedReader(new InputStreamReader(s.getInputStream()));  String str = bfrin.readLine();  System.out.println(str);    fis.close();  s.close();  }  }  class tcpserver  {  public static void main(String[] args) throws Exception  {  ServerSocket ss = new ServerSocket(10007);  Socket s = ss.accept();  String ip = s.getInetAddress().getHostAddress();  System.out.println(ip+"...连接成功");    InputStream in = s.getInputStream();  FileOutputStream fos = new FileOutputStream("server.jpg");    int len = 0;  byte[] buf = new byte[1024];  while ((len=in.read(buf))!=-1)  {  fos.write(buf,0,len);  }    PrintWriter pw = new PrintWriter(s.getOutputStream(),true);  pw.println("上传成功");    fos.close();  s.close();  ss.close();  }}

(5)练习

需求:

1.客户端登陆服务器,登陆三次错误,退出程序

2.允许多用户同时登陆

思路:

客户端:

1.建立Socket服务并指定要连接的主机地址以及程序端口

2.定义IO读取流读取键盘录入数据

3.获取Socket输出流发送数据

4.获取Socket读取流读取服务端返回的数据

5.关闭资源

服务端:

1.要模拟登陆功能需要一个数据库,可以用记事本做一个极简数据库

2.建立ServerSocket服务,并指定一个监听接口

3.获取Socket读取流读取客户端发送的数据

3.建立文件读取流读取数据库中的数据与客户端发送的数据进行比较

4.获取Socket输出流向客户端返回信息

5.关闭资源

代码演示:

  import java.io.*;  import java.net.*;  class TCPclient   {  public static void main(String[] args) throws Exception  {  Socket s = new Socket("127.0.0.1",10008);  //定义IO读取流读取键盘录入的数据  BufferedReader bfr = new BufferedReader(new InputStreamReader(System.in));  //获取Socket输出流发送数据  PrintWriter pw = new PrintWriter(s.getOutputStream(),true);  //获取Socket读取流读取服务端返回的数据  BufferedReader bfrin = new BufferedReader(new InputStreamReader(s.getInputStream()));  for (int x=1;x<=3;x++ )  {  String line = bfr.readLine();  if (line==null)  break;  pw.println(line);    String str = bfrin.readLine();  System.out.println("info:"+str);  if (str.contains("欢迎"))  break;  }  bfr.close();  s.close();  }  }    class TCPserver  {  public static void main(String[] args) throws Exception  {  ServerSocket ss = new ServerSocket(10008);  while (true)  {  Socket s = ss.accept();  new Thread(new ServerThread(s)).start();  }  }  }  class ServerThread implements Runnable  {  private Socket s;  ServerThread(Socket s)  {  this.s = s;  }  public void run()  {  String ip = s.getInetAddress().getHostAddress();  System.out.println(ip+"....connected");  try  {  for (int x=1;x<=3 ;x++ )  {  //Socket流接收客户端发送的数据  BufferedReader bfrin = new BufferedReader(  new InputStreamReader(s.getInputStream()));  //定义IO读取流查找建立的极简数据库  BufferedReader bfr = new BufferedReader(new FileReader("user.txt"));  PrintWriter pw = new PrintWriter(s.getOutputStream(),true);  String str = bfrin.readLine();  if(str==null)  break;  String name=null;  Boolean flag = false;  while ((name=bfr.readLine())!=null)  {  if (name.equals(str))  {  flag = true;  break;  }   }  if (flag)  {  System.out.println(ip+"...已登陆");  pw.println("登陆成功,欢迎进入");  break;  }  else  {  System.out.println(ip+"...尝试登陆");  pw.println(str+"用户名不存在");  }  }  s.close();  }  catch (Exception e)  {  throw new RuntimeException("效验失败");  }    }  }

6)练习:一个极简仿QQ聊天界面代码示例

服务端:

  import java.awt.*;  import java.awt.event.*;  import java.io.*;  import java.net.*;  //服务端  class Demo  {  public static void main(String[] args) throws Exception  {  liaotian lt = new liaotian();  }  }  class liaotian   {  //建立服务端Socket服务,并设定服务端端口  ServerSocket ss = new ServerSocket(12345);  Socket s = ss.accept();  String ip = s.getInetAddress().getHostAddress();  //定义Socket读取流读取客户端发送来的数据  private InputStream in = s.getInputStream();  //定义Socket输出流用来发送数据给客户端  private OutputStream out = s.getOutputStream();  liaotian() throws Exception  {  init();  }  private Frame f;  private Button b;  //定义两个文本区域,类似QQ聊天界面的读取区域和输入区域  private TextArea tax,tad;  public void init() throws Exception  {  //对软件窗体进行基本设置  f = new Frame("my window fuwuduan");  f.setBounds(300,100,500,600);  f.setLayout(new FlowLayout());    tax = new TextArea(8,63);  tad = new TextArea(20,63);  b = new Button("发送");    f.add(tad);  f.add(tax);  f.add(b);  myEvent();  //显示窗体  f.setVisible(true);  //使窗体大小不能被改变  f.setResizable(false);  tad.append(ip+"连接成功\r\n");  out.write("连接成功".getBytes());  while (true)//不断的接收数据  {  byte[] buf = new byte[1024];  int len = in.read(buf);  String strr = new String(buf,0,len);  tad.append("客户端IP-"+ip+":"+strr+"\r\n");  }    }  private void send() throws Exception//发送数据  {  String str = tax.getText()+" ";  tad.append("我:"+str+"\r\n");  tax.setText("");  out.write(str.getBytes());  }  private void myEvent() throws Exception  {  f.addWindowListener(new WindowAdapter()  {  public void windowClosing(WindowEvent e)  {  System.exit(0);    }  });  b.addActionListener(new ActionListener()   {  public void actionPerformed(ActionEvent e)   {  try  {  send();  }  catch (Exception e1)  {  throw new RuntimeException("asdfas");  }  }  });  }  }

客户端:

  import java.awt.*;  import java.awt.event.*;  import java.io.*;  import java.net.*;  //客户端  class Demo  {  public static void main(String[] args) throws Exception  {  liaotian lt = new liaotian();  }  }  class liaotian   {  //这里改成服务器主机的IP地址,“12345”为服务器端口  Socket s = new Socket("127.0.0.1",12345);  //定义Socket读取流读取服务端发送来的数据  private InputStream in = s.getInputStream();  //定义Socket输出流用来发送数据给服务端  private OutputStream out = s.getOutputStream();    liaotian() throws Exception  {  init();  }  private Frame f;  private Button b;  //定义两个文本区域,类似QQ聊天界面的读取区域和输入区域  private TextArea tax,tad;  public void init() throws Exception  {  //对软件窗体进行基本设置  f = new Frame("my window kehuduan");  f.setBounds(300,100,500,600);  f.setLayout(new FlowLayout());    tax = new TextArea(8,63);  tad = new TextArea(20,63);  b = new Button("发送");    f.add(tad);  f.add(tax);  f.add(b);  //加载窗体上的事件  myEvent();  //使窗体大小不能被改变  f.setResizable(false);  //显示窗体  f.setVisible(true);  while (true)//不断的接收数据  {  byte[] buf = new byte[1024];  int len = in.read(buf);  String strr = new String(buf,0,len);    tad.append("主机:"+strr+"\r\n");  }    }  private void send() throws Exception//发送数据  {  String str = tax.getText()+" ";  tad.append("我:"+str+"\r\n");  //在发送之前将输入区域里面的数据清空  tax.setText("");  out.write(str.getBytes());  }  private void myEvent() throws Exception  {  f.addWindowListener(new WindowAdapter()  {  public void windowClosing(WindowEvent e)  {  System.exit(0);    }  });  //点击"发送"按钮发送数据  b.addActionListener(new ActionListener()   {  public void actionPerformed(ActionEvent e)   {  try  {  send();  }  catch (Exception e1)  {  throw new RuntimeException("发送失败");  }  }  });  }}

7)自定义服务端

需求:自定义一个服务端向客户短发送一条数据,用IE浏览器作为客户端连接服务端 接收数据

代码如下:

  import java.io.*;  import java.net.*;  class tcpserver   {  public static void main(String[] args) throws Exception  {  ServerSocket ss = new ServerSocket(11000);  Socket s = ss.accept();    System.out.println(s.getInetAddress().getHostAddress());  //获取Socket输出流发送数据  PrintWriter out = new PrintWriter(s.getOutputStream(),true);    out.println("<font size='3' color='red'>客户端你好!</font>");    s.close();  ss.close();  }  }











0 0
原创粉丝点击