Java Socket编程
Java之网络编程应用(一:基础篇)
什么事Socket?
IP地址和端口号组成了所谓的socket,socket是网络上运行的程序之间双向通信链路的终结点,是TCP和UDP的基础。
Java中的网络支持?
针对网络通信的不同层次,Java提供的网络功能有四大类:
- InetAddress:用于标识网上的硬件资源。
- URL:统一资源定位符,通过URL可以直接读取或写入网络上的数据。
- Sockets:使用TCP协议实现网络通信的Socket相关的类。
- Datagram:使用UDP协议,将数据保存在数据报中,通过网络进行通信。
Java中的InetAddress应用
1 public class TestInetAddress {
2
3 public static void main(String[] args) throws UnknownHostException {
4 //获取本机的InetAddress实例
5 InetAddress address = InetAddress.getLocalHost();
6 System.out.println("计算机名:"+address.getHostName());
7 System.out.println("IP地址:"+address.getHostAddress());
8 byte[] bytes = address.getAddress();//获取字节数组形式的IP地址
9 System.out.println("字节数组形式的IP:"+Arrays.toString(bytes));
10 System.out.println("address:"+address);//直接输出InetAddress对象
11 }
12
13 }
Java中的URL应用
1 public class TestUrl {
2 public static void main(String[] args) {
3 try {
4 //创建一个URL实例
5 URL imooc = new URL("http://www.imooc.com");
6 //?后面表示参数,3后面表示锚点
7 URL url = new URL(imooc,"/index.html?username=tom#test");
8 System.out.println("协议:"+url.getProtocol());
9 System.out.println("主机名称:"+url.getHost());
10 //如果未指定端口号,则使用默认的端口号,此时getPort()方法返回值为-1
11 System.out.println("端口号:"+url.getPort());
12 System.out.println("文件路径:"+url.getPath());
13 System.out.println("文件名:"+url.getFile());
14 System.out.println("相对路径:"+url.getRef());
15 System.out.println("查询字符串:"+url.getQuery());
16 } catch (MalformedURLException e) {
17 e.printStackTrace();
18 }
19 }
20 }
使用URL读取网页内容:
1.通过URL对象的openStream()方法可以得到指定资源的输入流。
2.通过输入流可以读取,访问网络上的数据。
1 public class TestUrlReader {
2 public static void main(String[] args) {
3 try {
4 //创建一个URL实例
5 URL url = new URL("http://www.baidu.com");
6 //通过url的openStream()方法获取URL对象所表示的资源的字节输入流
7 InputStream is = url.openStream();
8 //将字节输入流转换为字符输入流
9 InputStreamReader isr = new InputStreamReader(is,"utf-8");
10 //为字符输入流添加缓冲
11 BufferedReader br = new BufferedReader(isr);
12 //读取数据
13 String data = br.readLine();
14 while(data!=null){//循环读取数据
15 System.out.println(data);
16 data = br.readLine();
17 }
18 //关闭流
19 br.close();
20 isr.close();
21 is.close();
22 } catch (MalformedURLException e) {
23 e.printStackTrace();
24 } catch (IOException e) {
25 e.printStackTrace();
26 }
27 }
28 }
Java的Socket通信:
Java基于tcp协议实现网络通信的类有两个:
- 客户端的Socket类
- 服务器端的ServerSocket类
使用Java的socket通信实现用户登录响应功能:
服务器端:
1 public class Server {
2 public static void main(String[] args) {
3 try {
4 //1.创建一个服务器端Socket,即ServerSocket,指定绑定的端口,并监听此端口
5 ServerSocket serverSocket = new ServerSocket(8888);
6 //2.调用accept()方法开始监听,等待客户端的连接
7 System.out.println("***服务器即将启动,等待客户端的连接****");
8 Socket socket = serverSocket.accept();
9 //3.获取输入流,并读取客户端信息
10 InputStream is = socket.getInputStream();//字节输入流
11 InputStreamReader isr = new InputStreamReader(is);//将字节流转换成字符流
12 BufferedReader br = new BufferedReader(isr);//为输入流添加缓冲
13
14 String info = null;
15 while((info=br.readLine())!=null){
16 System.out.println("我是服务器,客户端说:"+info);
17 }
18 //4.获取输出流,响应客户端请求
19 OutputStream os = socket.getOutputStream();
20 PrintWriter pw = new PrintWriter(os);//包装为打印流
21 pw.write("欢迎您");
22 pw.flush();//调用flush方法将缓冲输出
23
24 //5.关闭资源
25 pw.close();
26 os.close();
27 br.close();
28 isr.close();
29 is.close();
30 socket.close();
31 serverSocket.close();
32 } catch (IOException e) {
33 e.printStackTrace();
34 }
35 }
36 }
客户端:
1 public class Client {
2 public static void main(String[] args) {
3 try {
4 //1.创建客户端socket,指定服务器地址和端口
5 Socket socket = new Socket("localhost",8888);
6 //2.获取输出流,向服务器端发送信息
7 OutputStream os = socket.getOutputStream();//字节输出流
8 PrintWriter pw = new PrintWriter(os);//将输出流包装成打印流
9 pw.write("用户名:admin 密码:123");
10 pw.flush();
11 socket.shutdownOutput();//关闭输出流
12 //3.获取输入流,用来读取服务器端的响应信息
13 InputStream is = socket.getInputStream();
14 BufferedReader br = new BufferedReader(new InputStreamReader(is));
15 String info = null;
16 while((info=br.readLine())!=null){
17 System.out.println("我是客户端,服务器端说:"+info);
18 }
19 //4.关闭资源
20 br.close();
21 is.close();
22 pw.close();
23 os.close();
24 socket.close();
25 } catch (UnknownHostException e) {
26 e.printStackTrace();
27 } catch (IOException e) {
28 e.printStackTrace();
29 }
30 }
31 }
应用多线程来实现服务器与多客户端之间的通信:
实现步骤:
- 服务器端创建ServerSocket,循环调用accept()等待客户端连接。
- 客户端创建一个Socket并请求和服务器端连接。
- 服务器端接受客户端的请求,创建socket与该客户建立专线连接。
- 建立连接的两个socket在一个单独的线程上对话。
- 服务器端继续等待新的连接。
创建线程类:
1 public class ServerThread extends Thread{
2 //和本线程相关的Socket
3 Socket socket = null;
4 public ServerThread(Socket socket){
5 this.socket = socket;
6 }
7 //线程执行的操作,响应客户端的请求
8 public void run() {
9 //获取输入流,并读取客户端信息
10 InputStream is = null;
11 InputStreamReader isr = null;
12 BufferedReader br = null;
13 OutputStream os = null;
14 PrintWriter pw = null;
15 try {
16 is = socket.getInputStream();
17 // 字节输入流
18 isr = new InputStreamReader(is);// 将字节流转换成字符流
19 br = new BufferedReader(isr);// 为输入流添加缓冲
20 String info = null;
21 while ((info = br.readLine()) != null) {
22 System.out.println("我是服务器,客户端说:" + info);
23 }
24 socket.shutdownInput();//关闭输入流
25 // 4.获取输出流,响应客户端请求
26 os = socket.getOutputStream();
27 pw = new PrintWriter(os);// 包装为打印流
28 pw.write("欢迎您");
29 pw.flush();// 调用flush方法将缓冲输出
30 } catch (IOException e1) {
31 e1.printStackTrace();
32 }finally{
33 // 5.关闭资源
34 try {
35 if(pw!=null)
36 pw.close();
37 if(os!=null)
38 os.close();
39 if(br!=null)
40 br.close();
41 if(isr!=null)
42 isr.close();
43 if(is!=null)
44 is.close();
45 if(socket!=null)
46 socket.close();
47 } catch (IOException e) {
48 e.printStackTrace();
49 }
50 }
51 }
52 }
修改服务器端代码
1 public class Server1 {
2 public static void main(String[] args) {
3 try {
4 // 1.创建一个服务器端Socket,即ServerSocket,指定绑定的端口,并监听此端口
5 ServerSocket serverSocket = new ServerSocket(8888);
6 Socket socket = null;
7 //记录客户端的数量
8 int count =0;
9 System.out.println("***服务器即将启动,等待客户端的连接****");
10 //循环监听等待客户端的监听
11 while(true){
12 //调用accept()方法开始监听,等待客户端的连接
13 socket = serverSocket.accept();
14 //创建一个新的线程
15 ServerThread serverThread = new ServerThread(socket);
16 //启动线程
17 serverThread.start();
18 count++;//统计客户端数量
19 System.out.println("客户端的数量:"+count);
20 //获取客户端IP
21 InetAddress address = socket.getInetAddress();
22 System.out.println("当前客户端的IP是:"+address.getAddress());
23 }
24 } catch (IOException e) {
25 e.printStackTrace();
26 }
27 }
28 }