Javaネットワークプログラミング
ネットワーク プログラミングとは、ネットワークで接続された複数のデバイス (コンピューター) 上で実行されるプログラムを作成することを指します。
java.net パッケージの J2SE API は、低レベルの通信の詳細を提供するクラスとインターフェイスで構成されます。これらのクラスとインターフェイスを直接使用して、通信の詳細ではなく問題の解決に集中できます。
java.net パッケージは、次の 2 つの一般的なネットワーク プロトコルのサポートを提供します。
- TCP : TCP は、Transmission Control Protocol の頭字語で、2 つのアプリケーション間の信頼性の高い通信を保証します。TCP/IP として知られるインターネット プロトコルに一般的に使用されます。
- UDP : UDP は User Datagram Protocol の略で、コネクションレス型プロトコルです。アプリケーション間で送信されるデータを提供するデータ パケット。
このチュートリアルでは、次の 2 つのトピックに焦点を当てます。
接続が確立された後は、I/O ストリームを使用して通信が実行されます。各ソケットには出力ストリームと入力ストリームがあります。クライアントの出力ストリームはサーバーの入力ストリームに接続され、クライアントの入力ストリームはサーバーの出力ストリームに接続されます。
TCP は双方向通信プロトコルであるため、データは 2 つのデータ ストリームを通じて同時に送信できます。以下は、ソケットを実装するために一部のクラスによって提供される便利なメソッドの完全なセットです。
ServerSocket クラスのメソッド
サーバー アプリケーションは、java.net.ServerSocket クラスを使用してポートを取得し、クライアントの要求を待機します。
ServerSocket クラスには 4 つのコンストラクターがあります。
シリアルナンバー | メソッドの説明 |
1 | public ServerSocket(int port) throws IOException 特定のポートにバインドされたサーバー ソケットを作成します。 |
2 | public ServerSocket(int port, int backlog) throws IOException 指定されたバックログを使用してサーバー ソケットを作成し、それを指定されたローカル ポート番号にバインドします。 |
3 | public ServerSocket(int port, int backlog, InetAddress address) throws IOException 指定されたポート、リスニング バックログ、およびバインド先のローカル IP アドレスを持つサーバーを作成します。 |
4 | public ServerSocket() throws IOException アンバインドされたサーバーソケットを作成します。 |
アンバインドされたサーバーソケットを作成します。ServerSocket コンストラクターが例外をスローしない場合は、アプリケーションが指定されたポートに正常にバインドされ、クライアント要求をリッスンしていることを意味します。
ServerSocket クラスの一般的なメソッドをいくつか示します。
シリアルナンバー | メソッドの説明 |
1 | public int getLocalPort() このソケットがリッスンしているポートを返します。 |
2 | public Socket accept() throws IOException このソケットへの接続をリッスンして受け入れます。 |
3 | public void setSoTimeout(int timeout) タイムアウト値をミリ秒単位で指定して、SO_TIMEOUT を有効または無効にします。 |
4 | public void binding(SocketAddress host, int backlog) は、 ServerSocket を特定のアドレス (IP アドレスとポート番号) にバインドします。 |
Socket クラスのメソッド
java.net.Socket クラスは、クライアントとサーバーの両方が相互に通信するために使用するソケットを表します。クライアントはインスタンス化を通じて Socket オブジェクトを取得する必要があり、サーバーは accept() メソッドの戻り値を通じて Socket オブジェクトを取得します。
Socket クラスには 5 つのコンストラクターがあります。
シリアルナンバー | メソッドの説明 |
1 | public Socket(String host, int port) throws UnknownHostException, IOException. ストリーム ソケットを作成し、指定されたホストの指定されたポート番号に接続します。 |
2 | public Socket(InetAddress host, int port) throws IOException ストリーム ソケットを作成し、指定された IP アドレスの指定されたポート番号に接続します。 |
3 | public Socket(String host, int port, InetAddress localAddress, int localPort) throws IOException. ソケットを作成し、指定されたリモート ホスト上の指定されたリモート ポートに接続します。 |
4 | public Socket(InetAddress host, int port, InetAddress localAddress, int localPort) throws IOException. ソケットを作成し、指定されたリモート アドレス上の指定されたリモート ポートに接続します。 |
5 | public Socket() は、 システムのデフォルトタイプの SocketImpl を通じて未接続のソケットを作成します。 |
Socket コンストラクターが戻ると、単に Socket オブジェクトをインスタンス化するのではなく、指定されたサーバーとポートへの接続を実際に試みます。
興味深いメソッドの一部を以下に示します。クライアントとサーバーの両方が Socket オブジェクトを持っているため、クライアントとサーバーの両方がこれらのメソッドを呼び出すことができることに注意してください。
シリアルナンバー | メソッドの説明 |
1 | public void connect(SocketAddress host, int timeout) throws IOException タイムアウト値を指定して、このソケットをサーバーに接続します。 |
2 | public InetAddress getInetAddress() は ソケット接続のアドレスを返します。 |
3 | public int getPort() このソケットが接続されているリモート ポートを返します。 |
4 | public int getLocalPort() このソケットがバインドされているローカル ポートを返します。 |
5 | public SocketAddress getRemoteSocketAddress() このソケットが接続されているエンドポイントのアドレスを返します。接続されていない場合は null を返します。 |
6 | public InputStream getInputStream() throws IOException このソケットの入力ストリームを返します。 |
7 | public OutputStream getOutputStream() throws IOException このソケットの出力ストリームを返します。 |
8 | public void close() throws IOException このソケットを閉じます。 |
InetAddress クラスのメソッド
このクラスは、インターネット プロトコル (IP) アドレスを表します。ソケット プログラミングのより便利な方法を以下に示します。
シリアルナンバー | メソッドの説明 |
1 | static InetAddress getByAddress(byte[] addr) 生の IP アドレスを指定して InetAddress オブジェクトを返します。 |
2 | static InetAddress getByAddress(String host, byte[] addr) 指定されたホスト名と IP アドレスから InetAddress を作成します。 |
3 | static InetAddress getByName(String host) 在给定主机名的情况下确定主机的 IP 地址。 |
4 | String getHostAddress() 返回 IP 地址字符串(以文本表现形式)。 |
5 | String getHostName() 获取此 IP 地址的主机名。 |
6 | static InetAddress getLocalHost() 返回本地主机。 |
7 | String toString() 将此 IP 地址转换为 String。 |
Socket 客户端实例
如下的GreetingClient 是一个客户端程序,该程序通过socket连接到服务器并发送一个请求,然后等待一个响应。
// 文件名 GreetingClient.java
import java.net.*;
import java.io.*;
public class GreetingClient
{
public static void main(String [] args)
{
String serverName = args[0];
int port = Integer.parseInt(args[1]);
try
{
System.out.println("Connecting to " + serverName
+ " on port " + port);
Socket client = new Socket(serverName, port);
System.out.println("Just connected to "
+ client.getRemoteSocketAddress());
OutputStream outToServer = client.getOutputStream();
DataOutputStream out =
new DataOutputStream(outToServer);
out.writeUTF("Hello from "
+ client.getLocalSocketAddress());
InputStream inFromServer = client.getInputStream();
DataInputStream in =
new DataInputStream(inFromServer);
System.out.println("Server says " + in.readUTF());
client.close();
}catch(IOException e)
{
e.printStackTrace();
}
}
}
Socket 服务端实例
如下的GreetingServer 程序是一个服务器端应用程序,使用Socket来监听一个指定的端口。
// 文件名 GreetingServer.java
import java.net.*;
import java.io.*;
public class GreetingServer extends Thread
{
private ServerSocket serverSocket;
public GreetingServer(int port) throws IOException
{
serverSocket = new ServerSocket(port);
serverSocket.setSoTimeout(10000);
}
public void run()
{
while(true)
{
try
{
System.out.println("Waiting for client on port " +
serverSocket.getLocalPort() + "...");
Socket server = serverSocket.accept();
System.out.println("Just connected to "
+ server.getRemoteSocketAddress());
DataInputStream in =
new DataInputStream(server.getInputStream());
System.out.println(in.readUTF());
DataOutputStream out =
new DataOutputStream(server.getOutputStream());
out.writeUTF("Thank you for connecting to "
+ server.getLocalSocketAddress() + "\nGoodbye!");
server.close();
}catch(SocketTimeoutException s)
{
System.out.println("Socket timed out!");
break;
}catch(IOException e)
{
e.printStackTrace();
break;
}
}
}
public static void main(String [] args)
{
int port = Integer.parseInt(args[0]);
try
{
Thread t = new GreetingServer(port);
t.start();
}catch(IOException e)
{
e.printStackTrace();
}
}
}
编译以上 java 代码,并执行以下命令来启动服务,使用端口号为 6066:
$ java GreetingServer 6066
Waiting for client on port 6066...
像下面一样开启客户端:
$ java GreetingClient localhost 6066
Connecting to localhost on port 6066
Just connected to localhost/127.0.0.1:6066
Server says Thank you for connecting to /127.0.0.1:6066
Goodbye!
- Socket 编程: 这是使用最广泛的网络概念,它已被解释地非常详细
- URL 处理
-
Socket 编程
套接字使用TCP提供了两台计算机之间的通信机制。 客户端程序创建一个套接字,并尝试连接服务器的套接字。
当连接建立时,服务器会创建一个Socket对象。客户端和服务器现在可以通过对Socket对象的写入和读取来进行通信。
java.net.Socket类代表一个套接字,并且java.net.ServerSocket类为服务器程序提供了一种来监听客户端,并与他们建立连接的机制。
以下步骤在两台计算机之间使用套接字建立TCP连接时会出现:
- 服务器实例化一个ServerSocket对象,表示通过服务器上的端口通信。
- 服务器调用 ServerSocket类 的accept()方法,该方法将一直等待,直到客户端连接到服务器上给定的端口。
- 服务器正在等待时,一个客户端实例化一个Socket对象,指定服务器名称和端口号来请求连接。
- Socket类的构造函数试图将客户端连接到指定的服务器和端口号。如果通信被建立,则在客户端创建一个Socket对象能够与服务器进行通信。
- 在服务器端,accept()方法返回服务器上一个新的socket引用,该socket连接到客户端的socket。
URL 类方法
在 java.net 包中定义了URL类,该类用来处理有关URL的内容。对于URL类的创建和使用,下面分别进行介绍。
java.net.URL提供了丰富的URL构建方式,并可以通过java.net.URL来获取资源。
序号 | 方法描述 |
---|---|
1 | public URL(字符串协议,字符串主机,int端口,字符串文件)抛出格式错误的URLException。 通过给定的参数(协议、主机名、端口号、文件名)创建URL。 |
2 | public URL(String protocol, String host, String file) 抛出 MalformURLException 使用指定的协议、主机名、文件名创建URL,端口使用协议的默认端口。 |
3 | public URL(String url) 抛出 MalformURLException 通过给定的 URL字符串创建URL |
4 | public URL(URL context, String url) 抛出 MalformURLException 使用基地址和相对URL创建 |
URL类中包含了很多方法用于访问URL的各个部分,具体方法及描述如下:
序号 | 方法描述 |
---|---|
1 | public String getPath() 返回URL路径部分。 |
2 | public String getQuery() 返回URL查询部分。 |
3 | public String getAuthority() 获取此 URL 的授权部分。 |
4 | public int getPort() 返回URL端口部分 |
5 | public int getDefaultPort() 返回协议的默认端口号。 |
6 | public String getProtocol() 返回URL的协议 |
7 | public String getHost() 返回URL的主机 |
8 | public String getFile() 返回URL文件名部分 |
9 | public String getRef() 获取此 URL 的锚点(也称为“引用”)。 |
10 | public URLConnection openConnection() throws IOException 打开一个URL连接,并运行客户端访问资源。 |
实例
以上实例演示了使用 java.net 的URL类获取URL的各个部分参数:
// 文件名 : URLDemo.java
import java.net.*;
import java.io.*;
public class URLDemo
{
public static void main(String [] args)
{
try
{
URL url = new URL("http://www.w3cschool.cn/index.html?language=cn#j2se");
System.out.println("URL is " + url.toString());
System.out.println("protocol is "
+ url.getProtocol());
System.out.println("authority is "
+ url.getAuthority());
System.out.println("file name is " + url.getFile());
System.out.println("host is " + url.getHost());
System.out.println("path is " + url.getPath());
System.out.println("port is " + url.getPort());
System.out.println("default port is "
+ url.getDefaultPort());
System.out.println("query is " + url.getQuery());
System.out.println("ref is " + url.getRef());
}catch(IOException e)
{
e.printStackTrace();
}
}
}
以上实例编译运行结果如下:
URL is //www.w3cschool.cn/index.html?language=cn#j2se
protocol is http
authority is www.w3cschool.cn
file name is /index.htm?language=cn
host is www.w3cschool.cn
path is /index.html
port is -1
default port is 80
query is language=cn
ref is j2se
URLConnections 类方法
openConnection() 返回一个 java.net.URLConnection。
例如:
-
如果你连接HTTP协议的URL, openConnection() 方法返回 HttpURLConnection 对象。
-
如果你连接的URL为一个 JAR 文件, openConnection() 方法将返回 JarURLConnection 对象。
-
等等...
URLConnection 方法列表如下:
序号 | 方法描述 |
---|---|
1 | Object getContent() 检索URL链接内容 |
2 | Object getContent(Class[] classes) 检索URL链接内容 |
3 | String getContentEncoding() 返回头部 content-encoding 字段值。 |
4 | int getContentLength() 返回头部 content-length字段值 |
5 | String getContentType() 返回头部 content-type 字段值 |
6 | int getLastModified() 返回头部 last-modified 字段值。 |
7 | long getExpiration() 返回头部 expires 字段值。 |
8 | long getIfModifiedSince() 返回对象的 ifModifiedSince 字段值。 |
9 | public void setDoInput(boolean input) URL 连接可用于输入和/或输出。如果打算使用 URL 连接进行输入,则将 DoInput 标志设置为 true;如果不打算使用,则设置为 false。默认值为 true。 |
10 | public void setDoOutput(boolean output) URL 连接可用于输入和/或输出。如果打算使用 URL 连接进行输出,则将 DoOutput 标志设置为 true;如果不打算使用,则设置为 false。默认值为 false。 |
11 | public InputStream getInputStream() 抛出 IOException 返回URL的输入流,用于读取资源 |
12 | public OutputStream getOutputStream() throws IOException 返回URL的输出流, 用于写入资源。 |
13 | public URL getURL() 返回 URLConnection 对象连接的 URL |
实例
以下实例中URL采用了HTTP 协议。openConnection 返回HttpURLConnection对象。
// 文件名 : URLConnDemo.java
import java.net.*;
import java.io.*;
public class URLConnDemo
{
public static void main(String [] args)
{
try
{
URL url = new URL("http://www.w3cschool.cn");
URLConnection urlConnection = url.openConnection();
HttpURLConnection connection = null;
if(urlConnection instanceof HttpURLConnection)
{
connection = (HttpURLConnection) urlConnection;
}
else
{
System.out.println("Please enter an HTTP URL.");
return;
}
BufferedReader in = new BufferedReader(
new InputStreamReader(connection.getInputStream()));
String urlString = "";
String current;
while((current = in.readLine()) != null)
{
urlString += current;
}
System.out.println(urlString);
}catch(IOException e)
{
e.printStackTrace();
}
}
}
以上实例编译运行结果如下:
$ java URLConnDemo
.....a complete HTML content of home page of amrood.com.....
Java 发送邮件
Java 发送邮件
使用Java应用程序发送E-mail十分简单,但是首先你应该在你的机器上安装JavaMail API 和Java Activation Framework (JAF) 。
你可以在 JavaMail (Version 1.2) 下载最新的版本。
你可以再 在JAF (Version 1.1.1)下载最新的版本。
下载并解压这些文件,最上层文件夹你会发现很多的jar文件。你需要将mail.jar和激活.jar 添加到你的CLASSPATH中。
如果你使用第三方邮件服务器如QQ的SMTP服务器,可查看文章底部用户认证完整的实例。
发送一封简单的 E-mail
下面是一个发送简单E-mail的例子。假设你的localhost已经连接到网络。
// 文件名 SendEmail.java
import java.util.*;
import javax.mail.*;
import javax.mail.internet.*;
import javax.activation.*;
public class SendEmail
{
public static void main(String [] args)
{
// 收件人电子邮箱
String to = "[email protected]";
// 发件人电子邮箱
String from = "[email protected]";
// 指定发送邮件的主机为 localhost
String host = "localhost";
// 获取系统属性
Properties properties = System.getProperties();
// 设置邮件服务器
properties.setProperty("mail.smtp.host", host);
// 获取默认session对象
Session session = Session.getDefaultInstance(properties);
try{
// 创建默认的 MimeMessage 对象
MimeMessage message = new MimeMessage(session);
// Set From: 头部头字段
message.setFrom(new InternetAddress(from));
// Set To: 头部头字段
message.addRecipient(Message.RecipientType.TO,
new InternetAddress(to));
// Set Subject: 头部头字段
message.setSubject("This is the Subject Line!");
// 设置消息体
message.setText("This is actual message");
// 发送消息
Transport.send(message);
System.out.println("Sent message successfully....");
}catch (MessagingException mex) {
mex.printStackTrace();
}
}
}
编译并运行这个程序来发送一封简单的E-mail:
$ java SendEmail
Sent message successfully....
如果你想发送一封电子邮件给多个收件人,那么使用下面的方法来指定多个收件人ID:
void addRecipients(Message.RecipientType type,
Address[] addresses)
throws MessagingException
下面是对于参数的描述:
-
type:要被设置为TO, CC 或者BCC.这里CC 代表抄送、BCC 代表秘密抄送y.举例:Message.RecipientType.TO
-
地址: 这是电子邮件ID的数组。在指定电子邮件ID时,你将需要使用InternetAddress()方法。
发送一封 HTML 电子邮件
下面是一个发送HTML E-mail的例子。假设你的localhost已经连接到网络。
和上一个例子很相似,除了我们要使用setContent()方法来通过第二个参数为“text/html”,来设置内容来指定要发送HTML内容。
// 文件名 SendHTMLEmail.java
import java.util.*;
import javax.mail.*;
import javax.mail.internet.*;
import javax.activation.*;
public class SendHTMLEmail
{
public static void main(String [] args)
{
// 收件人电子邮箱
String to = "[email protected]";
// 发件人电子邮箱
String from = "[email protected]";
// 指定发送邮件的主机为 localhost
String host = "localhost";
// 获取系统属性
Properties properties = System.getProperties();
// 设置邮件服务器
properties.setProperty("mail.smtp.host", host);
// 获取默认的 Session 对象。
Session session = Session.getDefaultInstance(properties);
try{
// 创建默认的 MimeMessage 对象。
MimeMessage message = new MimeMessage(session);
// Set From: 头部头字段
message.setFrom(new InternetAddress(from));
// Set To: 头部头字段
message.addRecipient(Message.RecipientType.TO,
new InternetAddress(to));
// Set Subject: 头字段
message.setSubject("This is the Subject Line!");
// 发送 HTML 消息, 可以插入html标签
message.setContent("<h1>This is actual message</h1>",
"text/html" );
// 发送消息
Transport.send(message);
System.out.println("Sent message successfully....");
}catch (MessagingException mex) {
mex.printStackTrace();
}
}
}
编译并运行此程序来发送HTML e-mail:
$ java SendHTMLEmail
Sent message successfully....
发送带有附件的 E-mail
下面是一个发送带有附件的 E-mail的例子。假设你的localhost已经连接到网络。
// 文件名 SendFileEmail.java
import java.util.*;
import javax.mail.*;
import javax.mail.internet.*;
import javax.activation.*;
public class SendFileEmail
{
public static void main(String [] args)
{
// 收件人电子邮箱
String to = "[email protected]";
// 发件人电子邮箱
String from = "[email protected]";
// 指定发送邮件的主机为 localhost
String host = "localhost";
// 获取系统属性
Properties properties = System.getProperties();
// 设置邮件服务器
properties.setProperty("mail.smtp.host", host);
// 获取默认的 Session 对象。
Session session = Session.getDefaultInstance(properties);
try{
// 创建默认的 MimeMessage 对象。
MimeMessage message = new MimeMessage(session);
// Set From: 头部头字段
message.setFrom(new InternetAddress(from));
// Set To: 头部头字段
message.addRecipient(Message.RecipientType.TO,
new InternetAddress(to));
// Set Subject: 头字段
message.setSubject("This is the Subject Line!");
// 创建消息部分
BodyPart messageBodyPart = new MimeBodyPart();
// 消息
messageBodyPart.setText("This is message body");
// 创建多重消息
Multipart multipart = new MimeMultipart();
// 设置文本消息部分
multipart.addBodyPart(messageBodyPart);
// 附件部分
messageBodyPart = new MimeBodyPart();
String filename = "file.txt";
DataSource source = new FileDataSource(filename);
messageBodyPart.setDataHandler(new DataHandler(source));
messageBodyPart.setFileName(filename);
multipart.addBodyPart(messageBodyPart);
// 发送完整消息
message.setContent(multipart );
// 发送消息
Transport.send(message);
System.out.println("Sent message successfully....");
}catch (MessagingException mex) {
mex.printStackTrace();
}
}
}
编译并运行你的程序来发送一封带有附件的邮件。
$ java SendFileEmail
Sent message successfully....
用户认证部分
如果需要提供用户名和密码给e-mail服务器来达到用户认证的目的,你可以通过如下设置来完成:
props.put("mail.smtp.auth", "true");
props.setProperty("mail.user", "myuser");
props.setProperty("mail.password", "mypwd");
e-mail其他的发送机制和上述保持一致。
需要用户名密码验证邮件发送实例:
本实例以QQ邮件服务器为例,你需要在登录QQ邮箱后台在“设置”=》账号中开启POP3/SMTP服务 ,如下图所示:
Java 代码如下:
// 需要用户名密码邮件发送实例
//文件名 SendEmail2.java
//本实例以QQ邮箱为例,你需要在qq后台设置
import java.util.Properties;
import javax.mail.Authenticator;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.PasswordAuthentication;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
public class SendEmail2
{
public static void main(String [] args)
{
// 收件人电子邮箱
String to = "[email protected]";
// 发件人电子邮箱
String from = "[email protected]";
// 指定发送邮件的主机为 localhost
String host = "smtp.qq.com"; //QQ 邮件服务器
// 获取系统属性
Properties properties = System.getProperties();
// 设置邮件服务器
properties.setProperty("mail.smtp.host", host);
properties.put("mail.smtp.auth", "true");
// 获取默认session对象
Session session = Session.getDefaultInstance(properties,new Authenticator(){
public PasswordAuthentication getPasswordAuthentication(){
return new PasswordAuthentication("[email protected]", "qq邮箱密码"); //发件人邮件用户名、密码
}
});
try{
// 创建默认的 MimeMessage 对象
MimeMessage message = new MimeMessage(session);
// Set From: 头部头字段
message.setFrom(new InternetAddress(from));
// Set To: 头部头字段
message.addRecipient(Message.RecipientType.TO,
new InternetAddress(to));
// Set Subject: 头部头字段
message.setSubject("This is the Subject Line!");
// 设置消息体
message.setText("This is actual message");
// 发送消息
Transport.send(message);
System.out.println("Sent message successfully....from w3cschool.cn");
}catch (MessagingException mex) {
mex.printStackTrace();
}
}
}