Java网络编程
URL对象
-
URL类
-
URL(Uniform Resource Locator)
一致资源定位器的简称,表示Internet上某一资源的地址
-
URL的组成
protocol:resourceNamae
协议名指明获取资源所使用的的传输协议,如http、ftp等,资源名则是资源的完整地址,包括主机名、端口号或文件内部的一个引用。
-
获取URL对象属性
Public String getProtocol() Public String getHost() public String getPort() public String getFile()
-
URLConnection对象
-
一个URLConnection对象代表一个URL资源与Java程序的通讯连接,可以通过它对这个URL资源读或写。
-
与URL的区别
-
URL是单向的,URLConnection是双向的
-
可以查看服务器的响应消息的首部
-
可以设置客户端请求消息的首部
-
-
使用示例
关键步骤:构造一个URL对象,调用URL对象的
openConnection()
方法获取对应该URL的URLConnection对象。public class URLConnector { public static void main(String[] args) { try { URL cs = new URL("http://www.sina.com/"); URLConnection tc = cs.openConnection(); BufferedReader in = new BufferedReader(new InputStreamReader(tc.getInputStream())); String inputLine; while((inputLine = in.readLine()) != null) { System.out.println(inputLine); } in.close(); } catch (MalformedURLException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } }
Get与Post请求
-
示例
public static String sendGet(String url, String param) { String result = ""; BufferedReader in = null; try { String urlNameString = url + "?" +param; URL realUrl = new URL(urlNameString); URLConnection connection = realUrl.openConnection(); connection.setRequestProperty("accept", "*/*"); connection.setRequestProperty("connection", "Keep-Alive"); connection.connect(); in = new BufferedReader(new InputStreamReader(connection.getInputStream())); String line; while((line=in.readLine()) != null) { result += line; } } catch (MalformedURLException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } finally { try { if (in != null) { in.close(); } } catch (IOException e) { e.printStackTrace(); } return result; } } public static String sendPost(String url, String param) { PrintWriter out = null; BufferedReader in = null; String result = ""; try { URL realUrl = new URL(url); URLConnection connection = realUrl.openConnection(); connection.setRequestProperty("accept", "*/*"); connection.setRequestProperty("connection", "Keep-Alive"); connection.setDoOutput(true); out = new PrintWriter(connection.getOutputStream()); out.print(param); out.flush(); in = new BufferedReader(new InputStreamReader(connection.getInputStream())); String line; while((line=in.readLine()) != null) { result += line; } } catch (MalformedURLException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } finally { try { if (in != null) { in.close(); } } catch (IOException e) { e.printStackTrace(); } return result; } }
-
HttpURLConnection类
在URLConnection的基础上提供一系列针对http请求的内容
- HTTP状态码(例如HTTP_OK:200)
setRequestMethod
(设置请求方法GET\POST等)getResponseCode
(获取HTTP的响应)
Socket通信原理
-
TCP传输协议(Transport Control Protocol)
面向连接的能够提供可靠的流式数据传输的协议
URL,URLConnection,Sokcet,ServerSocket等类都使用TCP协议进行网络通讯。
-
socket通讯
网络上的两个程序通过一个双向的通讯连接实现数据的交换,这个双向链路的一端称为一个socket。
Socket通信实现
-
创建socket
使用Socket类构造
-
客户端socket的建立
-
服务端socket的建立
-
打开输入输出流
-
关闭socket
注意先关闭流再关闭socket
@TalkClient.java
import java.net.*; import java.io.*; public class TalkClient { public static void main(String[] args) { System.out.println("Client Start..."); try { Socket socket = new Socket("127.0.0.1", 8888); BufferedReader sin = new BufferedReader(new InputStreamReader(System.in)); PrintWriter os = new PrintWriter(socket.getOutputStream()); BufferedReader is = new BufferedReader(new InputStreamReader(socket.getInputStream())); String readline; readline = sin.readLine(); while (!readline.equals("bye")) { os.println(readline); os.flush(); System.out.println("Client:" + readline); System.out.println("Server:" + is.readLine()); readline = sin.readLine(); } os.close(); is.close(); socket.close(); } catch (UnknownHostException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } }
@TalkServer.java
public class TalkServer { public static void main (String[] args) { System.out.println("Server start..."); try { ServerSocket server = new ServerSocket(8888); Socket socket = server.accept(); String readline; BufferedReader is = new BufferedReader(new InputStreamReader(socket.getInputStream())); PrintWriter os = new PrintWriter(socket.getOutputStream()); BufferedReader sin = new BufferedReader(new InputStreamReader(System.in)); System.out.println("Client: "+is.readLine()); readline = sin.readLine(); while (!readline.equals("bye")) { os.println(readline); os.flush(); System.out.println("Server:" + readline); System.out.println("Client:" + is.readLine()); readline = sin.readLine(); } os.close(); is.close(); socket.close(); } catch (Exception e) { e.printStackTrace(); } } }
注意os.print()与os.println()的区别,不要被回车符坑了!!!
Socket多客户端通信
@MultiTalkClient.java
public class MultiTalkClient {
int num;
public static void main(String[] args) {
System.out.println("Client Start...");
try {
Socket socket = new Socket("127.0.0.1", 8888);
BufferedReader sin = new BufferedReader(new InputStreamReader(System.in));
PrintWriter os = new PrintWriter(socket.getOutputStream());
BufferedReader is = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String readline;
readline = sin.readLine();
while (!readline.equals("bye")) {
os.println(readline);
os.flush();
System.out.println("Client:" + readline);
System.out.println("Server:" + is.readLine());
readline = sin.readLine();
}
os.close();
is.close();
socket.close();
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
@ServerThread.java
public class ServerThread extends Thread {
Socket socket = null;
int clientNum;
public ServerThread(Socket socket, int num) {
this.socket = socket;
this.clientNum = num + 1;
}
@Override
public void run() {
try {
String line;
BufferedReader sin = new BufferedReader(new InputStreamReader(System.in));
PrintWriter os = new PrintWriter(socket.getOutputStream());
BufferedReader is = new BufferedReader(new InputStreamReader(socket.getInputStream()));
System.out.println("Client"+clientNum+":"+is.readLine());
line = sin.readLine();
while (!line.equals("bye")) {
os.println(line);
os.flush();
System.out.println("Server:" + line);
System.out.println("Client"+clientNum+":"+is.readLine());
line = sin.readLine();
}
os.close();
is.close();
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
@MultiTalkServer.java
public class MultiTalkServer {
static int clientNum = 0;
public static void main (String[] args) {
System.out.println("Server start...");
try {
ServerSocket serverSocket = null;
Boolean listening = true;
try {
serverSocket = new ServerSocket(8888);
} catch (IOException e) {
System.out.println("Could not listen on port:8888");
System.exit(-1);
}
while (listening) {
new ServerThread(serverSocket.accept(), clientNum).start();
clientNum++;
}
serverSocket.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
数据报通信
-
UDP(User Datagram Protocol)
非面向连接的提供不可靠的数据包式的数据传输协议。
DatagramPacket,DatagramSocket,MulticastSocket等类使用UDP协议进行网络通讯。
-
TCP(Transport Control Protocol)
面向连接的能够提供可靠的流式数据传输的协议。
URL,URLConnection,Socket,ServerSocket等类都使用TCP协议进行网络通讯。
-
区别
-
TCP有建立时间
-
UDP传输有大小限制:64k以内
-
TCP的应用:Telnet,ftp
-
UDP的应用:ping
-
-
使用数据报通信
DatagramSocket()
DatagramPacket()
-
收数据报
DatagramPacket packet = new DatagramPacket(buf,256); socket.recive(packet);
-
发数据报
DatagramPacket packet = new DatagramPacket(buf,buf.length,address,port); socket.send(packet);
-
示例
@QuoteClient.java
public class QuoteClient { public static void main(String[] args) throws IOException { if (args.length != 1) { System.out.println("Usage:java QuoteClient <hostname>"); return; } DatagramSocket socket = new DatagramSocket(); //send request byte[] buf = new byte[256]; InetAddress address = InetAddress.getByName(args[0]); DatagramPacket packet = new DatagramPacket(buf,buf.length,address,8888); socket.send(packet); //get response packet = new DatagramPacket(buf,buf.length); socket.receive(packet); //display response String received = new String(packet.getData()); System.out.println("Quote of the Moment:"+received); socket.close(); } }
@QuoteServerThread.java
public class QuoteServerThread extends Thread { protected DatagramSocket socket = null; protected BufferedReader in = null; protected boolean moreQuotes = true; public QuoteServerThread() throws SocketException { this("QuoteServerThread"); } public QuoteServerThread(String name) throws SocketException { super(name); socket = new DatagramSocket(8888); try { in = new BufferedReader(new FileReader("one-liners.txt")); } catch (FileNotFoundException e) { System.err.println("Could not open quote file. Serving time instead."); } } @Override public void run() { while(moreQuotes) { try { byte[] buf = new byte[256]; DatagramPacket packet = new DatagramPacket(buf,buf.length); socket.receive(packet); String dString = null; if (in == null) dString = new Date().toString(); else dString = getNextQuote(); buf = dString.getBytes(); //send response InetAddress address = packet.getAddress(); int port = packet.getPort(); packet = new DatagramPacket(buf,buf.length,address,port); socket.send(packet); } catch (IOException e) { e.printStackTrace(); moreQuotes = false; } } socket.close(); } protected String getNextQuote() { String res = null; try { if ((res = in.readLine()) == null) { in.close(); moreQuotes = false; res = "No more quotes."; } } catch (IOException e) { res = "IOException occured in server"; } return res; } }
@QuoteServer.java
public class QuoteServer { public static void main(String[] args) throws IOException { new QuoteServerThread().start(); } }
使用数据报进行广播通信
DatagramSocket只允许数据报发往一个目的地址
MulticastSocket将数据报以广播方式发送到该端口的所有客户
MulticastSocket用在客户端,监听服务器广播来的数据
-
示例
@MulticastClient.java
public class MulticastClient { public static void main(String[] args) throws IOException { MulticastSocket socket = new MulticastSocket(4396); InetAddress address = InetAddress.getByName("230.0.0.1"); socket.joinGroup(address); DatagramPacket packet; //get a few quotes for(int i=0;i<5;i++) { byte[] buf = new byte[256]; packet = new DatagramPacket(buf,buf.length); socket.receive(packet); String received = new String(packet.getData()); System.out.println("Quote of the Moment:"+received); } socket.leaveGroup(address); socket.close(); } }
@MulticastServerThread.java
public class MulticastServerThread extends QuoteServerThread{ private long FIVE_SECOND = 5000; public MulticastServerThread() throws IOException { super("MulticastServerThread"); } @Override public void run() { while (moreQuotes) { try { byte[] buf = new byte[256]; String dString = null; if (in == null) dString = new Date().toString(); else dString = getNextQuote(); buf = dString.getBytes(); //send it InetAddress group = InetAddress.getByName("230.0.0.1"); DatagramPacket packet = new DatagramPacket(buf,buf.length,group,4396); socket.send(packet); //sleep for a while try { sleep((long)(Math.random()*FIVE_SECOND)); } catch (InterruptedException e) { e.printStackTrace(); } } catch (IOException e) { e.printStackTrace(); moreQuotes = false; } } socket.close(); } }
@MulticastServer.java
public class MulticastServer { public static void main(String[] args) throws IOException { new MulticastServerThread().start(); } }
网络聊天程序
@ChatFrame.java
public class ChatFrame extends JFrame implements ActionListener {
JTextField tf;
JTextArea ta;
JScrollPane sp;
JButton send;
JPanel p;
int port;
String s = "";
String myID;
Date date;
ServerSocket server;
Socket mySocket;
BufferedReader is;
PrintWriter os;
String line;
public ChatFrame(String ID,String remoteID,String IP,int port, boolean isServer) {
super(ID);
myID = ID;
this.port = port;
ta = new JTextArea();
ta.setEditable(false);
sp = new JScrollPane(ta);
this.setSize(330,400);
this.setResizable(false);
try{
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (Exception e) {
e.printStackTrace();
}
this.getContentPane().add(sp,"Center");
p = new JPanel();
this.getContentPane().add(p,"South");
send = new JButton("发送");
tf = new JTextField(20);
tf.requestFocus();
p.add(tf);
p.add(send);
this.setDefaultCloseOperation(EXIT_ON_CLOSE);
this.setVisible(true);
send.addActionListener(this);
tf.addActionListener(this);
if(isServer) {
try {
server = null;
try {
server = new ServerSocket(port);
}catch (Exception e) {
e.printStackTrace();
}
mySocket = null;
try {
mySocket = server.accept();
}catch (Exception e) {
e.printStackTrace();
}
is = new BufferedReader(new InputStreamReader(mySocket.getInputStream()));
os = new PrintWriter(mySocket.getOutputStream());
}catch (Exception e) {
e.printStackTrace();
}
}
else {
try {
mySocket = new Socket(IP,port);
os = new PrintWriter(mySocket.getOutputStream());
is = new BufferedReader(new InputStreamReader(mySocket.getInputStream()));
} catch (Exception e) {
e.printStackTrace();
}
}
while (true) {
try {
line = is.readLine();
date = new Date();
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String currentTime = formatter.format(date);
s+=currentTime+" "+remoteID+"说:\n"+line+"\n";
ta.setText(s);
} catch (Exception e) {
e.printStackTrace();
}
}
}
@Override
public void actionPerformed(ActionEvent actionEvent) {
date = new Date();
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String currentTime = formatter.format(date);
s+=currentTime+" "+myID+"说:\n"+tf.getText()+"\n";
ta.setText(s);
os.println(tf.getText());
os.flush();
tf.setText("");
tf.requestFocus();
}
}
@ChatServerFrame.java
public class ChatServerFrame {
public static void main(String[] args) {
ChatFrame cserver = new ChatFrame("Cat","Dog","localhost",4396,true);
}
}
@ChatClientFrame.java
public class ChatClientFrame {
public static void main(String[] args) {
ChatFrame cclient = new ChatFrame("Dog","Cat","localhost",4396,false);
}
}
实际运行如下图所示: