【Java笔记】网络编程基础
2017-08-01 16:04
232 查看
ServerSocket和Socket类:
ServerSocket是服务器用的“网络插口”可以定义,端口号等;Socket是客户端用的"网络插口",用来连接制定IP、端口等;
下面直接用代码和其中的注释演示一个网络通信的例子:在线聊天室;
客户端如下:
服务器显示:
服务器已经准备好了 客户端可以连接了
欢迎用户127.0.0.1进入聊天室
欢迎用户127.0.0.1进入聊天室
client1:
你好(此为输入)
127.0.0.1:嗯嗯,你好呀
client2:
127.0.0.1:你好
嗯嗯,你好呀(此为输入)
自己和自己聊天(笑),下次用swing等工具加上图形界面就更好玩啦
ServerSocket是服务器用的“网络插口”可以定义,端口号等;Socket是客户端用的"网络插口",用来连接制定IP、端口等;
下面直接用代码和其中的注释演示一个网络通信的例子:在线聊天室;
package Test01; /** * 群聊:Server:接收某一位成员的消息 转发给其他成员(收到消息才发出去 收发两个动作是单线程执行) Client:发送自己的消息 接受别的消息 * (收发互不干扰 收消息与发消息应该使用两个单独的线程) * * 服务器端 ServerSocket 1. 指定服务器这个程序在本机上的端口号(0~65535 0~1023(系统预先装订的程序占用了)) 2. * 监听客户端的连接 3. 交互 * */ import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; import java.net.ServerSocket; import java.net.Socket; import java.util.ArrayList; import java.util.List; public class Server { private static final int PORT = 20001; // 定义一个集合来放我们的客户端的socket对象,当做用户列表 private static List<Socket> onLineUsers = new ArrayList<>(); public static void main(String[] args) { ServerSocket server = null; try { // 用能传入端口的构造器穿件ServerSocket对象 server = new ServerSocket(PORT); System.out.println("服务器已经准备好了 客户端可以连接了"); } catch (IOException e) { // 这个异常是因为如果我们定义的端口已经被其他软件占用了,那么我们就不能成功连接 System.out.println("端口被占用了!"); } while (true) { Socket client = null; try { /* * 监听客户端的连接请求,accept这个方法监听时,处于阻塞状态, 也就是说程序会停在这先不往下执行,直到监听到了连接请求 */ client = server.accept(); } catch (IOException e) { System.out.println("监听客户端时出现异常"); } synchronized (onLineUsers) { // 这部分代码需要同步,因为我们的表单这个集合是共享变量; onLineUsers.add(client); } ServerThread serverThread = new ServerThread(client, onLineUsers); Thread t = new Thread(serverThread); t.start(); } } } //写 class ServerThread implements Runnable { private Socket client; private List<Socket> onLineUsers; private DataInputStream dis; private String clientIp; //定义构造器,参数有Socket对象,和表单集合 public ServerThread(Socket client, List<Socket> onLineUsers) { this.client = client; this.onLineUsers = onLineUsers; this.clientIp = client.getInetAddress().getHostAddress(); try { this.dis = new DataInputStream(client.getInputStream()); } catch (IOException e) { System.out.println("服务器取得用户输入流时出现异常,用户已下线"); // 用户下线,我们把它从表单中删除 synchronized (onLineUsers) { onLineUsers.remove(client); } } } @Override public void run() { String msg = null; DataOutputStream dos; System.out.println("欢迎用户" + clientIp + "进入聊天室"); // 不断地收消息 while (true) { if (dis != null) { try { msg = dis.readUTF(); } catch (IOException e) { System.out.println("服务器读取用户消息时出现异常,用户已下线"); synchronized (onLineUsers) { onLineUsers.remove(client); } break; } if (msg == null || msg.equals("")) { // 不转发消息 } else { // 转发消息,需要遍历表单中每一个用户 for (Socket s : onLineUsers) { //因为这个时候表单里已近add了此用户,此客户端没必要对自己也发一次消息,所以我们进行一次判断;如果不是再进行下一步操作 if (s != client) { try { //Socket有getOutputStream的方法,我们创建对象并调用此方法将msg输入进流 dos = new DataOutputStream(s.getOutputStream()); dos.writeUTF(clientIp + ":" + msg); } catch (IOException e) { synchronized (onLineUsers) { onLineUsers.remove(s); } } } } } } } } }
客户端如下:
package Test01; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; import java.net.Socket; import java.util.Scanner; /** * 客户端:Socket * 发消息 收消息 */ public class Client { private static DataInputStream dis ; private static DataOutputStream dos; public static void main(String[] args) { Socket client =null; try { //创建对象的时候发起连接请求,其中localhost指本机ip地址,20001指端口,在这里我客户端和服务器都在我的电脑上运行; client = new Socket("localhost",20001); } catch (IOException e) { System.out.println("连接服务器失败"); } try { //创建数据流输入输出的两个对象 dis = new DataInputStream(client.getInputStream()); dos = new DataOutputStream(client.getOutputStream()); } catch (IOException e) { System.out.println("服务器端异常 客户端无法获取输入输出流!"); } //开启线程 RecMsg rec = new RecMsg(dis); SendMsg send = new SendMsg(dos); Thread recMsg = new Thread(rec); Thread sendMsg = new Thread(send); recMsg.start(); sendMsg.start(); } } class RecMsg implements Runnable{ private DataInputStream dis ; public RecMsg(DataInputStream dis) { this.dis = dis; } @Override public void run() { //收消息----输入流 while(true){ String msg = null; try { //读入数据,读入在流中的数据,注意read的格式应与服务器呼应 msg = dis.readUTF(); } catch (IOException e) { System.out.println("服务器端出现异常 用户读取消息失败"); } System.out.println(msg); } } } class SendMsg implements Runnable{ private DataOutputStream dos; private Scanner scanner = new Scanner(System.in); public SendMsg(DataOutputStream dos) { this.dos = dos; } @Override public void run() { //发消息----输出流 while(true){ String msg2Send = scanner.next(); if(msg2Send!=null&&(!msg2Send.equals(""))){ try { dos.writeUTF(msg2Send); } catch (IOException e) { System.out.println("服务器端出现异常 用户发送消息失败"); } } } } }输出结果:(我们先运行服务器,)
服务器显示:
服务器已经准备好了 客户端可以连接了
欢迎用户127.0.0.1进入聊天室
欢迎用户127.0.0.1进入聊天室
client1:
你好(此为输入)
127.0.0.1:嗯嗯,你好呀
client2:
127.0.0.1:你好
嗯嗯,你好呀(此为输入)
自己和自己聊天(笑),下次用swing等工具加上图形界面就更好玩啦
相关文章推荐
- Java学习笔记之网络编程基础-通过URL获取网络图片
- java 从零开始,学习笔记之基础入门<网络编程_带QQ模拟功能>(二十)
- 黑马程序员_java基础笔记(08)...GUI,网络编程,正则表达式
- Java基础知识强化之网络编程笔记04:UDP之发送端的数据来自于键盘录入案例
- Java学习笔记之网络编程基础-根据域名自动到DNS上获取IP地址
- Java基础笔记五GUI和网络编程
- Java学习笔记(七、网络编程基础)
- Java基础知识强化之网络编程笔记06:TCP之TCP协议发送数据 和 接收数据
- Java基础知识强化之网络编程笔记03:UDP之UDP协议发送数据 和 接收数据
- Java基础知识强化之网络编程笔记01:InetAddress类的概述和使用
- Java基础知识强化之网络编程笔记05:UDP之多线程实现聊天室案例
- Java学习笔记之网络编程基础-通过URLConnection获取HTML页面
- Java基础知识强化之网络编程笔记02:Socket通信原理图解
- 黑马程序员_java基础笔记(08)...GUI,网络编程,正则表达式
- 黑马程序员 JAVA基础之网络编程笔记
- 黑马程序员_JAVA网络编程基础概念+URL类学习笔记
- 黑马程序员_java基础笔记(08)...GUI,网络编程,正则表达式
- 黑马程序员—21—java基础:有关网络编程的学习笔记和学习心得体会
- 黑马程序员————Java基础日常笔记---网络编程
- Java基础笔记之网络编程