一、目的
- 了解URL地址
- 使用socket实现数据发送
- 实现双向传递
- 实现对聊和群聊功能
二、学习内容
1.网络编程
在两台不同的计算机之间传递数据
- 1.qq聊天
- 2.打开网易App 刷新界面 就有数据
- 3.打开浏览器 网页 www.baidu.com
客户端:手机App 浏览器 桌面QQ
服务器端:存储/处理数据
2.URL:统一的资源定位
http://www.baidu.com/search?code=android
http//https:传输协议 TCP/IP
www.baidu.com:域名 表示一台网络中的电脑
ipv4 ipv6地址:唯一标识一台网络中的计算机
32位:四个部分每个是8个字节
3.DNS服务器:域名解析
将www.baidu.com类型的域名解析为对应的ip地址
search 对应的后台程序文件 php java jsp
?表示运行这个程序需要传递的参数
code=Android code是服务器端规定的字段
& 如果有多个参数使用&符号链接
4.ip地址、端口号
ip地址:唯一标识某一台电脑
端口号:唯一标识电脑上的某一个进程(程序)80
数据传输:TCP/IP协议
TCP:面向连接的、安全的 打电话
UDP:面向无连接的 不安全 但快
5.网络中的数据传输:
Socket实现->套接字
Socket类:客户端
ServerSocket:服务器端
- 读取数据:服务器读取 客户端读取
BufferedReader->InputStreamReader->socket.getInputStream() - 读取终端
BufferedReader->InputStreamReader->System.in - 输出:客户端输出 服务器端输出
BufferedWriter->OutputStreamWriter->socket.getOutputStream()
PrintStream->socket.getOutputStream()
三、技术的使用
1.模拟客户端
class Client{
public static void main(String[] args) throws IOException {
//1.创建用于通信的socket
// 指明和谁通信:ip地址 端口号
Socket socket=new Socket("127.0.0.1",8989);
// 接收服务器端的数据
BufferedReader br=new BufferedReader(new InputStreamReader(socket.getInputStream()));
//socket.getInputStream();
// 向服务器发送数据
//socket.getOutputStream();
String line=null;
while ((line=br.readLine())!=null){
System.out.println(line);
}
//客户端向服务器端发送数据
PrintStream ps=new PrintStream(socket.getOutputStream());
ps.println("你好啊");
socket.shutdownOutput();
}
}
2.模拟服务器端
class Server{
public static void main(String[] args) throws IOException {
//1.创建服务器端的serversocket
ServerSocket ss=new ServerSocket(8989);
//2.获取连接的客户端的socket
Socket clientSocket=ss.accept();
//3.向客户端发送数据
//BufferedWriter bw=new BufferedWriter(new OutputStreamWriter(clientSocket.getOutputStream()));
PrintStream ps=new PrintStream(clientSocket.getOutputStream());
ps.println("登录成功");
//输出完毕
clientSocket.shutdownOutput();
//4.服务器端接收客户端发来的数据
BufferedReader br=new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
String line=null;
while ((line=br.readLine())!=null){
System.out.println(line);
}
}
}
3.实现上传图片
class Client{
public static void main(String[] args) throws IOException {
//连接服务器端 获取socket
Socket socket=new Socket("127.0.0.1",8787);
//创建服务器端对应的输入流 用于接收服务器端发来的数据
BufferedReader br=new BufferedReader(new InputStreamReader(socket.getInputStream()));
System.out.println(br.readLine());
//向服务器端发送文件(图片)
//1.将文件写入到内存
String path="C:\\Users\\asus\\Desktop\\草图1.png";
FileInputStream fis=new FileInputStream(path);
//2.创建字节流
BufferedOutputStream bos=new BufferedOutputStream(socket.getOutputStream());
byte[] buf=new byte[1024];
int len=-1;
while ((len=fis.read(buf))!=-1){
bos.write(buf,0,len);
}
socket.shutdownOutput();
}
}
class Server{
public static void main(String[] args) throws IOException {
//创建服务器端的ServerSocket
ServerSocket ss=new ServerSocket(8787);
//监听客户端连接
//当有客户端来连接这个服务器 就可以得到对应的socket对象
//当没有客户端来连接 服务器一直在这里等待
Socket socket=ss.accept();
//创建客户端对应的输出流 用于向这个客户端发送数据
PrintStream ps=new PrintStream(socket.getOutputStream());
ps.println("连接成功 可以输出数据了!");
BufferedInputStream bis=new BufferedInputStream(socket.getInputStream());
//文件对应的输出流
String path="C:\\Users\\asus\\Desktop\\Android\\Android Studio\\java\\src\\main\\java\\day12\\media\\草图1.png";
FileOutputStream fos=new FileOutputStream(path);
byte[] buf=new byte[1024];
int len=-1;
while ((len=bis.read(buf))!=-1){
fos.write(buf,0,len);
}
}
}
四、聊天功能的实现
1.对聊
(1)功能及实现方法
客户端和服务器端都可以随意地发送内容
从终端输入
- 客户端:
主线程:接收终端输入 将终端的输入发送给服务器端
子线程:接收服务器端发来的数据 - 服务器端:
主线程:接收终端输入 将终端输入发送给客服端
子线程:接收客户端端发来的数据
(2)代码实现
class Client{
public static void main(String[] args) throws IOException {
Socket socket=new Socket("127.0.0.1",9000);
//用一个子线程处理服务器端数据
new Thread(new ClientThread(socket)).start();
//主线程处理终端输入 发送给服务器端
BufferedReader keyin=new BufferedReader(new InputStreamReader(System.in));
PrintStream ps=new PrintStream(socket.getOutputStream());
String line=null;
while ((line=keyin.readLine())!=null){
ps.println(line);
}
}
}
/**
* 创建一个子线程处理客户端接收服务器端数据
*
*/
class ClientThread implements Runnable{
private Socket socket;
//保存操作的socket对象
public ClientThread(Socket socket){
this.socket=socket;
}
@Override
public void run() {
BufferedReader br=null;
try {
//获取服务器端的输入流对象
br=new BufferedReader(new InputStreamReader(socket.getInputStream()));
//读取数据
String line=null;
while ((line=br.readLine())!=null){
System.out.println(line);
}
} catch (IOException e) {
System.out.println("网络出错 请重新登录");
System.exit(-1);
}finally {
try {
if (br!=null){
br.close();
}
if (socket!=null){
socket.close();
}
}catch (IOException ex){
}
}
}
}
class Server{
public static void main(String[] args) throws IOException {
ServerSocket ss=new ServerSocket(9000);
//获取客户端的socket
Socket socket=ss.accept();
//创建子线程 处理客户端输入信息
new ServerThread(socket).start();
//终端输入流对象
BufferedReader keyin=new BufferedReader(new InputStreamReader(System.in));
//客户端的输出流对象
PrintStream ps=new PrintStream(socket.getOutputStream());
//读取终端的输入 将输入输出给客户端
String line=null;
while ((line=keyin.readLine())!=null){
ps.println(line);
}
}
}
/**
* 创建一个子线程处理服务器端接收客户端的数据
*/
class ServerThread extends Thread{
private Socket socket;
public ServerThread(Socket socket){
this.socket=socket;
}
@Override
public void run() {
BufferedReader br=null;
try {
br=new BufferedReader(new InputStreamReader(socket.getInputStream()));
String line=null;
while ((line=br.readLine())!=null){
System.out.println(line);
}
} catch (IOException e) {
System.out.println("网络异常 请重新登录");
System.exit(-1);
}finally {
//关闭输入输出流
//关闭对应的socket链接
try {
if (br!=null){
br.close();
}
if (socket!=null){
socket.close();
}
}catch (IOException e){
e.printStackTrace();
}
}
}
}
2.群聊
(1)实现方法
在对聊的基础上让服务器端维护一个数组【socket】
(2)代码实现
class Client{
public static void main(String[] args) throws IOException {
Socket socket=new Socket("10.129.28.253",6666);
//用一个子线程处理服务器端数据
new Thread(new ClientThread(socket)).start();
//主线程处理终端输入 发送给服务器端
BufferedReader keyin=new BufferedReader(new InputStreamReader(System.in));
PrintStream ps=new PrintStream(socket.getOutputStream());
String line=null;
while ((line=keyin.readLine())!=null){
ps.println(line);
}
}
}
/**
* 创建一个子线程处理客户端接收服务器端数据
*
*/
class ClientThread implements Runnable{
private Socket socket;
//保存操作的socket对象
public ClientThread(Socket socket){
this.socket=socket;
}
@Override
public void run() {
BufferedReader br=null;
try {
//获取服务器端的输入流对象
br=new BufferedReader(new InputStreamReader(socket.getInputStream()));
//读取数据
String line=null;
while ((line=br.readLine())!=null){
System.out.println(line);
}
} catch (IOException e) {
System.out.println("网络出错 请重新登录");
System.exit(-1);
}finally {
try {
if (br!=null){
br.close();
}
if (socket!=null){
socket.close();
}
}catch (IOException ex){
}
}
}
}
/**
* 1.如何实现群聊
* 在服务器端维护一个数组【socket】
* 2.私聊
* 3.给每个人起名字
*/
class Server{
//保存每一个链接过来的socket对象
public static ArrayList<Socket>sockets=new ArrayList<>();
public static void main(String[] args) throws IOException {
ServerSocket ss=new ServerSocket(7777);
//不停的等待客户端来连接
while (true) {
Socket socket = ss.accept();
//当有客户端连接过来了 就保存
sockets.add(socket);
//开启一个线程处理每一个客户端的输入
new ServerThread(socket).start();
}
}
}
/**
* 创建一个子线程处理服务器端接收客户端的数据
*/
class ServerThread extends Thread{
private Socket socket;
public ServerThread(Socket socket){
this.socket=socket;
}
@Override
public void run() {
BufferedReader br=null;
try {
br=new BufferedReader(new InputStreamReader(socket.getInputStream()));
String line=null;
while ((line=br.readLine())!=null){
//群发消息
//遍历Server维护的数组
for (Socket s:Server.sockets){
//向socket对应的客户端发送消息
PrintStream ps=new PrintStream(s.getOutputStream());
ps.println(line);
}
}
} catch (IOException e) {
System.out.println("网络异常 请重新登录");
System.exit(-1);
}finally {
//关闭输入输出流
//关闭对应的socket链接
try {
if (br!=null){
br.close();
}
if (socket!=null){
socket.close();
}
}catch (IOException e){
e.printStackTrace();
}
}
}
}