四、 网络

目录

4.1 连接到服务器

4.1.1 使用telnet

4.1.2 用Java连接服务器

4.1.3 套接字超时

4.1.1 因特网地址

4.2 实现服务器

4.2.1 服务器套接字

4.2.2 为多个客户提供服务

4.2.3 半关闭

4.3 可中断套接字

4.4 获取Web数

4.4.1 URL和URI

4.4.2 使用URLConnection获取信息

4.4.3 提交表单数据

4.5 发送Mail


 

4.1 连接到服务器

4.1.1 使用telnet

telnet time-a.nist.gov 13

当你开始使用time-a.nost.gov在端口13上建立telnet对话时,网络软件中有一段代码非常清楚的知道应该将字符串“time-a.nist.gov"转换为正确的IP地址129.6.15.28

4.1.2 用Java连接服务器

package Section4;

import java.net.*;
import java.util.Scanner;
import java.io.*;
public class test1 {
	public static void main(String []args) throws IOException {
		try(Socket s= new Socket("time-a.nist.gov",13)){
			Scanner in = new Scanner(s.getInputStream(),"UTF-8");
			{
				while(in.hasNextLine()) {
					String line=in.nextLine();
					System.out.println(line);
				}
			}
		}
	}
}

UnkownHostException是IOException的一个子类。

实际上,java.net包提供的编程接口与操作文件时所用的接口基本相同

java.net.Socket:

 

4.1.3 套接字超时

对于不同的应用,应该确认合理的超时值。

package Section4;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.util.Scanner;

public class test2 {

	public static void main(String []args) throws IOException {
		try{
			Socket s= new Socket("time-a.nist.gov",13);//会一直阻塞到连接到服务器,
			//添加超时这样做
			Socket s1=new Socket();
			s1.connect(new InetSocketAddress("time-a.nist.gov",13),10);
			s.setSoTimeout(10000);  //10s超时
			//这些操作会在超时时抛出SocketTimeoutException异常
			Scanner in = new Scanner(s.getInputStream(),"UTF-8");
			{
				while(in.hasNextLine()) {
					String line=in.nextLine();
					System.out.println(line);
				}
			}
		}finally {
			
		}
	}

}

4.1.1 因特网地址

package Section4;

import java.net.InetAddress;
import java.net.UnknownHostException;

public class test3 {
	public static void main(String []args) throws UnknownHostException{
		if(args.length>0) {
			String host=args[0];
			InetAddress[] addressed=InetAddress.getAllByName(host);
			for(InetAddress a:addressed) {
				System.out.println(a);
			}
		}else {
			InetAddress addressed=InetAddress.getLocalHost();
			System.out.println(addressed);
		}
	}
}

命令行执行java

java.net.InetAddress:

4.2 实现服务器

4.2.1 服务器套接字

 

package Section4;

import java.io.*;
import java.util.*;
import java.net.*;

public class test4 {

	public static void main(String[] args) throws IOException{
		// TODO Auto-generated method stub
		//建立服务器套接字,建立一个负责监控端口8189的服务器
		try(ServerSocket s = new ServerSocket(8189)){
			//等待客户连接。直到有人通过网络发送了正确的连接请求,并以此连接到了端口上。该方法返回一个已经建立的Socket对象
			try(Socket incoming = s.accept()){
				InputStream inStream = incoming.getInputStream();
				OutputStream outStream = incoming.getOutputStream();
				//本章中,通过套接字发送文本,所以将流转换成扫描器和写入?
				try(Scanner in = new Scanner(inStream,"UTF-8")){
					PrintWriter out= new PrintWriter(new OutputStreamWriter(outStream,"UTF-8"),true);
					out.println("Hello,Welcom to Roe Wang。Enter BYE to Exit");
					//客户输入
					boolean done=false;
					while(!done&&in.hasNextLine()) {
						String line = in.nextLine();
						out.println("Echo: "+line);
						if(line.trim().equals("BYE")) done = true;
					}
				}
			}
		}
	}

}

编译运行程序。在命令行界面中执行

telnet localhost 8189

java.net.ServerSocket:

4.2.2 为多个客户提供服务

package Section4;

import java.io.*;
import java.net.*;
import java.util.*;
/**
* 使用多线程
*/
public class test5 {

	public static void main(String[] args) throws IOException{
		// TODO Auto-generated method stub
		try(ServerSocket s=new ServerSocket(8189)){
			int i=1;
			while(true) {
				Socket incoming = s.accept();
				System.out.println("Spawing:"+i);
				Runnable r= new ThreadedEchoHandler(incoming);
				Thread t= new Thread(r);
				t.start();
				i++;
			}
		}
	}

}
class ThreadedEchoHandler implements Runnable{
	private Socket incoming;
	public ThreadedEchoHandler(Socket incoming) {
		this.incoming=incoming;
	}

	@Override
	public void run() {
		try(InputStream inStream=incoming.getInputStream();
				OutputStream outStream=incoming.getOutputStream()){
			Scanner in =new Scanner(inStream,"UTF-8");
			PrintWriter out=new PrintWriter(new OutputStreamWriter(outStream,"UTF-8"),true);
			out.println("Hello");
			//客户输入
			boolean done=false;
			while(!done&&in.hasNextLine()) {
				String line = in.nextLine();
				out.println("Echo: "+line);
				if(line.trim().equals("BYE")) done = true;
			}
		}catch( IOException e) {
			e.printStackTrace();
		}
		
	}
}

4.2.3 半关闭

半关闭提供了这样一种能力:套接字连接的一端可以终止其输出,同时仍旧可以接收来自另一端的数据。

package Section4;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;

public class test6 {
	public static void main(String[] args) throws IOException{
		try(ServerSocket s = new ServerSocket(8189)){
			//等待客户连接。直到有人通过网络发送了正确的连接请求,并以此连接到了端口上。该方法返回一个已经建立的Socket对象
			try(Socket incoming = s.accept()){
				InputStream inStream = incoming.getInputStream();
				OutputStream outStream = incoming.getOutputStream();
				//本章中,通过套接字发送文本,所以将流转换成扫描器和写入?
				try(Scanner in = new Scanner(inStream,"UTF-8")){
					PrintWriter out= new PrintWriter(new OutputStreamWriter(outStream,"UTF-8"),true);
					out.println("Hello,Enter BYE to Exit");
					out.println("YiLing Song is a hundan");
					
					//关闭输出流
					incoming.shutdownOutput();
					//仍有输入流
					while(in.hasNextLine()) {
						//...
					}
				}
			}
		}
	}
}

4.3 可中断套接字

package Section4;

import java.awt.*;
import java.awt.event.*;
import java.util.*;
import java.net.*;
import java.io.*;
import java.nio.channels.*;
import javax.swing.*;

/**
 * This program shows how to interrupt a socket channel.
 * @author Cay Horstmann
 * @version 1.04 2016-04-27
 */
public class InterruptibleSocketTest
{
   public static void main(String[] args)
   {
      EventQueue.invokeLater(() ->
         {
            JFrame frame = new InterruptibleSocketFrame();
            frame.setTitle("InterruptibleSocketTest");
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            frame.setVisible(true);
         });
   }
}

class InterruptibleSocketFrame extends JFrame
{
   private Scanner in;
   private JButton interruptibleButton;
   private JButton blockingButton;
   private JButton cancelButton;
   private JTextArea messages;
   private TestServer server;
   private Thread connectThread;

   public InterruptibleSocketFrame()
   {
      JPanel northPanel = new JPanel();
      add(northPanel, BorderLayout.NORTH);

      final int TEXT_ROWS = 20;
      final int TEXT_COLUMNS = 60;
      messages = new JTextArea(TEXT_ROWS, TEXT_COLUMNS);
      add(new JScrollPane(messages));

      interruptibleButton = new JButton("Interruptible");
      blockingButton = new JButton("Blocking");

      northPanel.add(interruptibleButton);
      northPanel.add(blockingButton);

      interruptibleButton.addActionListener(event ->
         {
            interruptibleButton.setEnabled(false);
            blockingButton.setEnabled(false);
            cancelButton.setEnabled(true);
            connectThread = new Thread(() ->
               {
                  try
                  {
                     connectInterruptibly();
                  }
                  catch (IOException e)
                  {
                     messages.append("\nInterruptibleSocketTest.connectInterruptibly: " + e);
                  }
               });
            connectThread.start();
         });

      blockingButton.addActionListener(event ->
         {
            interruptibleButton.setEnabled(false);
            blockingButton.setEnabled(false);
            cancelButton.setEnabled(true);
            connectThread = new Thread(() ->
               {
                  try
                  {
                     connectBlocking();
                  }
                  catch (IOException e)
                  {
                     messages.append("\nInterruptibleSocketTest.connectBlocking: " + e);
                  }
               });
            connectThread.start();
         });

      cancelButton = new JButton("Cancel");
      cancelButton.setEnabled(false);
      northPanel.add(cancelButton);
      cancelButton.addActionListener(event -> 
         {
            connectThread.interrupt();
            cancelButton.setEnabled(false);
         });
      server = new TestServer();
      new Thread(server).start();
      pack();
   }

   /**
    * Connects to the test server, using interruptible I/O
    */
   public void connectInterruptibly() throws IOException
   {
      messages.append("Interruptible:\n");
      try (SocketChannel channel = SocketChannel.open(new InetSocketAddress("localhost", 8189)))
      {
         in = new Scanner(channel, "UTF-8");
         while (!Thread.currentThread().isInterrupted())
         {
            messages.append("Reading ");
            if (in.hasNextLine())
            {
               String line = in.nextLine();
               messages.append(line);
               messages.append("\n");
            }
         }
      }
      finally
      {
         EventQueue.invokeLater(() ->
            {
               messages.append("Channel closed\n");
               interruptibleButton.setEnabled(true);
               blockingButton.setEnabled(true);
            });
      }
   }

   /**
    * Connects to the test server, using blocking I/O
    */
   public void connectBlocking() throws IOException
   {
      messages.append("Blocking:\n");
      try (Socket sock = new Socket("localhost", 8189))
      {
         in = new Scanner(sock.getInputStream(), "UTF-8");
         while (!Thread.currentThread().isInterrupted())
         {
            messages.append("Reading ");
            if (in.hasNextLine())
            {
               String line = in.nextLine();
               messages.append(line);
               messages.append("\n");
            }
         }
      }
      finally
      {
         EventQueue.invokeLater(() ->
            {
               messages.append("Socket closed\n");
               interruptibleButton.setEnabled(true);
               blockingButton.setEnabled(true);
            });      
      }
   }

   /**
    * A multithreaded server that listens to port 8189 and sends numbers to the client, simulating
    * a hanging server after 10 numbers.
    */
   class TestServer implements Runnable
   {
      public void run()
      {
         try (ServerSocket s = new ServerSocket(8189))
         {
            while (true)
            {
               Socket incoming = s.accept();
               Runnable r = new TestServerHandler(incoming);
               Thread t = new Thread(r);
               t.start();
            }
         }
         catch (IOException e)
         {
            messages.append("\nTestServer.run: " + e);
         }
      }
   }

   /**
    * This class handles the client input for one server socket connection.
    */
   class TestServerHandler implements Runnable
   {
      private Socket incoming;
      private int counter;

      /**
       * Constructs a handler.
       * @param i the incoming socket
       */
      public TestServerHandler(Socket i)
      {
         incoming = i;
      }

      public void run()
      {
         try 
         {
            try
            {
               OutputStream outStream = incoming.getOutputStream();
               PrintWriter out = new PrintWriter(
                  new OutputStreamWriter(outStream, "UTF-8"),
                  true /* autoFlush */);
               while (counter < 100)
               {
                  counter++;
                  if (counter <= 10) out.println(counter);
                  Thread.sleep(100);
               }
            }
            finally
            {
               incoming.close();
               messages.append("Closing server\n");
            }
         }
         catch (Exception e)
         {
            messages.append("\nTestServerHandler.run: " + e);
         }
      }
   }
}

java.net.InetSocketAddress:

java.nio.channels.SocketChannel:

4.4 获取Web数

4.4.1 URL和URI

4.4.2 使用URLConnection获取信息

 如果想从某个Web资源获取更多的信息,那么应该使用URLConnection类,通过它能够得到比基本的URL更多的控制功能

 

JAVA提供了6个常用的方法用来访问常用的信息头类型的值,并在需要的时候把他们转换为数字类型

package Section4;

import java.util.*;
import java.nio.*;
import java.nio.charset.StandardCharsets;
import java.net.*;
import java.io.*;

public class test8 {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		try {
			String urlName;
			urlName="http://horst.com";
			URL url=new URL(urlName);
			//获得URLConnection对象
			URLConnection connection = url.openConnection();
			//set方法设置请求属性
			/*
			 * 访问一个有密码保护的Web页,这样做。
			String name="a";
			String password="b";
			String input =name+":"+password;
			Base64.Encoder encoder = Base64.getEncoder();
			String encoding =encoder.encodeToString(input.getBytes(StandardCharsets.UTF_8));
			connection.setRequestProperty("Authorization", "Basic"+encoding);
			*/
			//连接远程资源
			connection.connect();
			//查询头信息,还有其它的函数
			Map<String,List<String>> headers = connection.getHeaderFields();
			for(Map.Entry<String, List<String>> entry:headers.entrySet()) {
				String key=entry.getKey();
				for(String value:entry.getValue()) {
					System.out.println(key+": "+value);
				}
			}
			//没有哪种方法可以返回字段的数量,必须反复调用下列函数知道返回null为止
			String value=connection.getHeaderField(3); //n从1开始,第三个值,没有返回null
			String key=connection.getHeaderFieldKey(3);  //n从一开始,第三个值,没有返回null
			System.out.println("()()"+value+"  "+key);	
			//查询各标准字段
			System.out.println("----------");
	        System.out.println("getContentType: " + connection.getContentType());
	        System.out.println("getContentLength: " + connection.getContentLength());
	        System.out.println("getContentEncoding: " + connection.getContentEncoding());
	        System.out.println("getDate: " + connection.getDate());
	        System.out.println("getExpiration: " + connection.getExpiration());
	        System.out.println("getLastModifed: " + connection.getLastModified());
	        System.out.println("----------");
	        //访问资源数据
	        String encoding = connection.getContentEncoding();
	        if(encoding==null) encoding="UTF-8";
	        try(Scanner in = new Scanner(connection.getInputStream(),encoding)){
	        	for(int n=1;in.hasNextLine()&&n<=10;n++) {
	        		System.out.println(in.nextLine());
	        	}
	        }
			
		}catch(Exception e) {
			e.printStackTrace();
		}
	}

}

java.net.URL:

java.net.URLConnection:

4.4.3 提交表单数据

 

 

 

 

 

 

package post;

import java.io.*;
import java.net.*;
import java.nio.file.*;
import java.util.*;

/**
 * This program demonstrates how to use the URLConnection class for a POST request.
 * @version 1.40 2016-04-24
 * @author Cay Horstmann
 */
public class PostTest
{
   public static void main(String[] args) throws IOException
   {
      String propsFilename = args.length > 0 ? args[0] : "post/post.properties"; 
      Properties props = new Properties();
      try (InputStream in = Files.newInputStream(Paths.get(propsFilename)))
      {
         props.load(in);
      }
      String urlString = props.remove("url").toString();
      Object userAgent = props.remove("User-Agent");
      Object redirects = props.remove("redirects");
      CookieHandler.setDefault(new CookieManager(null, CookiePolicy.ACCEPT_ALL));
      String result = doPost(new URL(urlString), props, 
         userAgent == null ? null : userAgent.toString(), 
         redirects == null ? -1 : Integer.parseInt(redirects.toString()));
      System.out.println(result);
   }   

   /**
    * Do an HTTP POST.
    * @param url the URL to post to
    * @param nameValuePairs the query parameters
    * @param userAgent the user agent to use, or null for the default user agent
    * @param redirects the number of redirects to follow manually, or -1 for automatic redirects
    * @return the data returned from the server
    */
   public static String doPost(URL url, Map<Object, Object> nameValuePairs, String userAgent, int redirects)
         throws IOException
   {        
      HttpURLConnection connection = (HttpURLConnection) url.openConnection();
      if (userAgent != null)
         connection.setRequestProperty("User-Agent", userAgent);
      
      if (redirects >= 0)
         connection.setInstanceFollowRedirects(false);
      
      connection.setDoOutput(true);
      
      try (PrintWriter out = new PrintWriter(connection.getOutputStream()))
      {
         boolean first = true;
         for (Map.Entry<Object, Object> pair : nameValuePairs.entrySet())
         {
            if (first) first = false;
            else out.print('&');
            String name = pair.getKey().toString();
            String value = pair.getValue().toString();
            out.print(name);
            out.print('=');
            out.print(URLEncoder.encode(value, "UTF-8"));
         }
      }      
      String encoding = connection.getContentEncoding();
      if (encoding == null) encoding = "UTF-8";
            
      if (redirects > 0)
      {
         int responseCode = connection.getResponseCode();
         if (responseCode == HttpURLConnection.HTTP_MOVED_PERM 
               || responseCode == HttpURLConnection.HTTP_MOVED_TEMP
               || responseCode == HttpURLConnection.HTTP_SEE_OTHER) 
         {
            String location = connection.getHeaderField("Location");
            if (location != null)
            {
               URL base = connection.getURL();
               connection.disconnect();
               return doPost(new URL(base, location), nameValuePairs, userAgent, redirects - 1);
            }
            
         }
      }
      else if (redirects == 0)
      {
         throw new IOException("Too many redirects");
      }
         
      StringBuilder response = new StringBuilder();
      try (Scanner in = new Scanner(connection.getInputStream(), encoding))
      {
         while (in.hasNextLine())
         {
            response.append(in.nextLine());
            response.append("\n");
         }         
      }
      catch (IOException e)
      {
         InputStream err = connection.getErrorStream();
         if (err == null) throw e;
         try (Scanner in = new Scanner(err))
         {
            response.append(in.nextLine());
            response.append("\n");
         }
      }

      return response.toString();
   }
}

4.5 发送Mail

一旦连接到服务器,就可以发送一个邮件报头(采用SMTP格式,该格式很容易生成)。紧随其后的是邮件信息

package Section4;

import java.io.IOException;
import java.net.*;
import java.io.*;

public class test7 {
	public static void main(String []args) throws UnknownHostException, IOException{
		Socket s = new Socket("mail.qq.com",25);
		PrintWriter out= new PrintWriter(s.getOutputStream());
		String message =                   "HELO sending host\r\n"
				+ "MAIL FROM: 1984852655@qq.com\r\n"
				+ "RCPT TO: 2872718690@qq.com\r\n"
				+ "DATA\r\n"
				+ "Subject: Hello World\r\n"
				+ "\r\n"
				+"Hello May.do you get this?Please call me later.\r\n"
				+ ".\r\n"
				+ "QUIT\r\n";
		out.print(message);
		
	}
}

许多服务器都内置了检查功能,并且只接收来自授信用户的请求。所以,上面代码会

Exception in thread "main" java.net.ConnectException: Connection timed out: connect

使用下方代码可以顺利发送邮件:

package Section4;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.Properties;


import javax.mail.*;
import javax.mail.internet.*;
import javax.activation.*;

/**
 * Servlet implementation class SendEmail
 */

public class MailTest {
	private static final long serialVersionUID = 1L;
       
   
	public static void main(String[] args){
		// TODO Auto-generated method stub
	
	
        Properties props = new Properties();
        // 表示SMTP发送邮件,必须进行身份验证
        props.put("mail.smtp.auth", "true");
        //此处填写SMTP服务器
        props.put("mail.smtp.host", "smtp.qq.com");
        //端口号,QQ邮箱给出了两个端口,但是另一个我一直使用不了,所以就给出这一个587
        props.put("mail.smtp.port", "25");
        // 此处填写你的账号
        props.put("mail.user","1984852655@qq.com");
        // 此处的密码就是前面说的16位STMP口令
        props.put("mail.password","segpcfwwzsuugjjc");

        // 构建授权信息,用于进行SMTP进行身份验证
        Authenticator authenticator = new Authenticator() {

            protected PasswordAuthentication getPasswordAuthentication() {
                // 用户名、密码
                String userName = props.getProperty("mail.user");
                String password = props.getProperty("mail.password");
                return new PasswordAuthentication(userName, password);
            }
        };
        // 使用环境属性和授权信息,创建邮件会话
        Session mailSession = Session.getInstance(props, authenticator);
        // 创建邮件消息
        MimeMessage message = new MimeMessage(mailSession);
        // 设置发件人
        InternetAddress form;
		try {
			form = new InternetAddress(
			        props.getProperty("mail.user"));
		
			message.setFrom(form);
		

        // 设置收件人的邮箱
        InternetAddress to = new InternetAddress("2872718690@qq.com");
        message.setRecipient(Message.RecipientType.TO, to);

        // 设置邮件标题
        message.setSubject("测试邮件");

        // 设置邮件的内容体
        message.setContent("这是一封测试邮件", "text/html;charset=UTF-8");

        // 最后当然就是发送邮件啦
        Transport.send(message);
	} catch (AddressException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}catch (MessagingException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}	
	}

	

}

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值