网络编程就是如何在程序中实现两台计算机的通信。
IP地址的配置和检测
查看本机的IP地址:ipconfig
测试网络是否通畅:ping 目标IP地址
重要概念介绍
端口:
常用的Web服务器:Microsoft IIS Apache服务器 Tomcat服务器
网络通信协议:
Socket简介
通信链路的端点就被称为“套接字”(英文名Socket)
是提供给应用程序的接口
Socket的底层机制复杂,Java平台提供了一些简单的API,可以更简单有效的使用Socket开发而无需了解底层机制
java.net包
Socket、ServerSocket 、DatagramPacket 、DatagramSocket、 InetAddress
基于TCP协议的Socket编程:用来实现双向安全连接网络通信
Socket网络编程一般可以分成如下步骤进行:
建立连接 ---->打开Socket关联的输入输出流---->数据流中读写信息---->关闭所有的数据流和Socket
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
public class Server {
public static void main(String[] args) {
// 创建ServerSocket
ServerSocket ss =null;
Socket soc=null;
InputStream is=null;
BufferedReader br =null;
OutputStream os=null;
try {
ss = new ServerSocket(10088);
//侦听客户端的请求
soc=ss.accept();
//获取输入流接收客户端的请求信息
is=soc.getInputStream();
br = new BufferedReader(new InputStreamReader(is));
String str;
while((str=br.readLine())!=null){
System.out.println("这里是服务器端,接收到的客户端信息为:"+str);
}
//获取输出流向客户端发送响应信息
os=soc.getOutputStream();
String str2 = "用户名和密码正确,登录成功";
byte[] bytes = str2.getBytes();
os.write(bytes);
} catch (IOException e) {
e.printStackTrace();
}finally{
try {
os.close();
br.close();
is.close();
soc.close();
ss.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.Socket;
import java.net.UnknownHostException;
public class Client {
public static void main(String[] args) {
//创建Socket对象
Socket socket =null;
OutputStream os =null;
InputStream is =null;
BufferedReader br =null;
try {
//通信链路的客户端端点创建成功
socket = new Socket("localhost", 10088);
//获取输出流将登录信息发送给服务器端
os =socket.getOutputStream();
String str = "用户名:tom,密码:123456";
byte[] bytes=str.getBytes();
//输出信息
os.write(bytes);
System.out.println("向服务器发送请求成功!");
//关闭输出流
socket.shutdownOutput();
//获取输入流接收服务器端发送的响应信息
is = socket.getInputStream();
br = new BufferedReader(new InputStreamReader(is));
String str2;
while((str2=br.readLine())!=null){
System.out.println("这里是客户端,接收到的服务器发送来的响应信息为:"+str2);
}
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally{
try {
br.close();
is.close();
os.close();
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
Socket中实现对象的传递
import java.io.Serializable;
public class User implements Serializable {
private static final long serialVersionUID = 1L;
/** 用户名 */
private String loginName;
/** 用户密码 */
private String pwd;
public User() {
super();
}
public User(String loginName, String pwd) {
super();
this.loginName = loginName;
this.pwd = pwd;
}
public String getLoginName() {
return loginName;
}
public void setLoginName(String loginName) {
this.loginName = loginName;
}
public String getPwd() {
return pwd;
}
public void setPwd(String pwd) {
this.pwd = pwd;
}
}
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
public class LoginServer {
public static void main(String[] args) {
ServerSocket serverSocket = null;
Socket socket = null;
InputStream is = null;
ObjectInputStream ois = null;
OutputStream os = null;
try {
// 建立一个服务器Socket(ServerSocket),指定端口8800并开始监听
serverSocket = new ServerSocket(8800);
// 使用accept()方法等待客户端发起通信
socket = serverSocket.accept();
// 打开输入流
is = socket.getInputStream();
// 反序列化
ois = new ObjectInputStream(is);
// 获取客户端信息,即从输入流读取信息
User user = (User) ois.readObject();
if (user != null) {
System.out.println("我是服务器,客户登录信息为:" + user.getLoginName() + ","
+ user.getPwd());
}
// 给客户端一个响应,即向输出流中写入信息
String reply = "欢迎你,登录成功";
os = socket.getOutputStream();
os.write(reply.getBytes());
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} finally {
// 关闭资源
try {
os.close();
ois.close();
is.close();
socket.close();
serverSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.net.UnknownHostException;
public class LoginClient {
public static void main(String[] args) {
Socket socket = null;
OutputStream os = null;
ObjectOutputStream oos = null;
InputStream is = null;
BufferedReader br = null;
try {
// 建立客户端Socket连接,指定服务器的位置为本机以及端口为8800
socket = new Socket("localhost", 8800);
// 打开输出流
os = socket.getOutputStream();
// 对象序列化
oos = new ObjectOutputStream(os);
// 发送客户端信息,即向输出流中写入信息
User user = new User("Tom", "123456");
oos.writeObject(user);
socket.shutdownOutput();
// 接收服务器端的响应,即从输入流中读取信息
is = socket.getInputStream();
br = new BufferedReader(new InputStreamReader(is));
String reply;
while ((reply = br.readLine()) != null) {
System.out.println("我是客户端,服务器的响应为:" + reply);
}
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
br.close();
is.close();
oos.close();
os.close();
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
多线程处理多请求
采用多线程的方式
一个专门负责监听的应用主服务程序
一个专门负责处理请求的线程程序
import java.io.Serializable;
public class User implements Serializable{
private String loginName;
private String pwd;
public User() {
super();
}
public User(String loginName, String pwd) {
super();
this.loginName = loginName;
this.pwd = pwd;
}
public String getLoginName() {
return loginName;
}
public void setLoginName(String loginName) {
this.loginName = loginName;
}
public String getPwd() {
return pwd;
}
public void setPwd(String pwd) {
this.pwd = pwd;
}
}
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.OutputStream;
import java.net.Socket;
public class LoginThread extends Thread {
/*
* 示例03:升级示例02,实现多客户端的响应处理。
*
* 分析如下:
* (1)创建服务器端线程类,run()方法中实现对一个请求的响应处理。
* (2)修改服务器端代码,让服务器端Socket一直处于监听状态。
* (3)服务器端每监听到一个请求,创建一个线程对象并启动
*/
Socket socket = null;
//每启动一个线程,连接对应的Socket
public LoginThread(Socket socket) {
this.socket = socket;
}
//启动线程,即响应客户请求
public void run() {
InputStream is = null;
ObjectInputStream ois = null;
OutputStream os = null;
try {
//打开输入流
is = socket.getInputStream();
//反序列化
ois = new ObjectInputStream(is);
//获取客户端信息,即从输入流读取信息
User user = (User)ois.readObject();
if(user!=null){
System.out.println("我是服务器,客户登录信息为:"+user.getLoginName()+","+user.getPwd());
}
//给客户端一个响应,即向输出流中写入信息
os = socket.getOutputStream();
String reply = "欢迎你,登录成功";
os.write(reply.getBytes());
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}finally{
try {
os.close();
ois.close();
is.close();
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
public class LoginServer {
public static void main(String[] args) {
ServerSocket serverSocket = null;
try {
// 建立一个服务器Socket(ServerSocket)指定端口并开始监听
serverSocket = new ServerSocket(8800);
// 监听一直进行中
while (true) {
// 使用accept()方法等待客户发起通信
Socket socket = serverSocket.accept();
LoginThread loginThread = new LoginThread(socket);
loginThread.start();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.net.UnknownHostException;
public class LoginClient01 {
public static void main(String[] args) {
Socket socket = null;
OutputStream os = null;
ObjectOutputStream oos = null;
InputStream is = null;
BufferedReader br = null;
try {
// 建立客户端Socket连接,指定服务器的位置为本机以及端口为8800
socket = new Socket("localhost", 8800);
// 打开输出流
os = socket.getOutputStream();
// 对象序列化
oos = new ObjectOutputStream(os);
// 发送客户端信息,即向输出流中写入信息
User user = new User("Tom", "123456");
oos.writeObject(user);
socket.shutdownOutput();
// 接收服务器端的响应,即从输入流中读取信息
is = socket.getInputStream();
br = new BufferedReader(new InputStreamReader(is));
String reply;
while ((reply = br.readLine()) != null) {
System.out.println("我是客户端,服务器的响应为:" + reply);
}
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
br.close();
is.close();
oos.close();
os.close();
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.net.UnknownHostException;
public class LoginClient02 {
public static void main(String[] args) {
Socket socket = null;
OutputStream os = null;
ObjectOutputStream oos = null;
InputStream is = null;
BufferedReader br = null;
try {
// 建立客户端Socket连接,指定服务器的位置为本机以及端口为8800
socket = new Socket("localhost", 8800);
// 打开输出流
os = socket.getOutputStream();
// 对象序列化
oos = new ObjectOutputStream(os);
// 发送客户端信息,即向输出流中写入信息
User user = new User("Jack", "456789");
oos.writeObject(user);
socket.shutdownOutput();
// 接收服务器端的响应,即从输入流中读取信息
is = socket.getInputStream();
br = new BufferedReader(new InputStreamReader(is));
String reply;
while ((reply = br.readLine()) != null) {
System.out.println("我是客户端,服务器的响应为:" + reply);
}
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
br.close();
is.close();
oos.close();
os.close();
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
基于UDP协议的Socket编程
基于UDP协议的Socket网络编程步骤
利用 DatagramPacket 对象封装数据包----->利用 DatagramSocket 发送数据包----->利用 DatagramSocket 接收数据包----->利用 DatagramPacket 处理数据包
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketAddress;
import java.net.SocketException;
public class Receive {
public static void main(String[] args) {
DatagramSocket ds=null;
DatagramPacket dp = null;
DatagramPacket dpto = null;
// 创建DatagramPacket对象,用来准备接收数据
byte[] buf=new byte[1024];
dp=new DatagramPacket(buf,1024);
try {
//创建DatagramSocket对象,接收数据
ds=new DatagramSocket(8800);
ds.receive(dp);
//显示接收到的信息
String mess=new String(dp.getData(),0,dp.getLength());
System.out.println(dp.getAddress().getHostAddress()+"说:"+mess);
String reply="你好,我在,请咨询!";
//显示与本地对话框
System.out.println("我 说:" + reply);
// 创建DatagramPacket对象,封装数据
SocketAddress sa = dp.getSocketAddress();
dpto = new DatagramPacket(reply.getBytes(),
reply.getBytes().length, sa);
ds.send(dpto);
} catch (SocketException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally{
ds.close();
}
}
}
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
import java.net.UnknownHostException;
public class Send {
public static void main(String[] args) {
//
DatagramSocket ds=null;
InetAddress ia=null;
String mess="你好,我想咨询一个问题。";
System.out.println("我说:"+mess);
try {
//获取本地主机地址
ia=InetAddress.getByName("localhost");
//创建DatagramPacket对象,封装数据,向服务器发送数据
DatagramPacket dp=new DatagramPacket(mess.getBytes(),mess.getBytes().length,ia,8800);
//创建DatagramSocket对象,向服务器发送数据
ds=new DatagramSocket();
ds.send(dp);
byte[] buf=new byte[1024];
DatagramPacket dpre=new DatagramPacket(buf,buf.length);
ds.receive(dpre);
//显示接收到消息
String reply=new String(dpre.getData(), 0, dpre.getLength());
System.out.println(dpre.getAddress().getHostAddress() + "说:"+ reply);
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (SocketException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally{
ds.close();
}
}
}