一、目的
- 了解URL地址
- 使用socket實(shí)現(xiàn)數(shù)據(jù)發(fā)送
- 實(shí)現(xiàn)雙向傳遞
- 實(shí)現(xiàn)對(duì)聊和群聊功能
二、學(xué)習(xí)內(nèi)容
1.網(wǎng)絡(luò)編程
在兩臺(tái)不同的計(jì)算機(jī)之間傳遞數(shù)據(jù)
- 1.qq聊天
- 2.打開網(wǎng)易App 刷新界面 就有數(shù)據(jù)
- 3.打開瀏覽器 網(wǎng)頁 www.baidu.com
客戶端:手機(jī)App 瀏覽器 桌面QQ
服務(wù)器端:存儲(chǔ)/處理數(shù)據(jù)
2.URL:統(tǒng)一的資源定位
http://www.baidu.com/search?code=android
http//https:傳輸協(xié)議 TCP/IP
www.baidu.com:域名 表示一臺(tái)網(wǎng)絡(luò)中的電腦
ipv4 ipv6地址:唯一標(biāo)識(shí)一臺(tái)網(wǎng)絡(luò)中的計(jì)算機(jī)
32位:四個(gè)部分每個(gè)是8個(gè)字節(jié)
3.DNS服務(wù)器:域名解析
將www.baidu.com類型的域名解析為對(duì)應(yīng)的ip地址
search 對(duì)應(yīng)的后臺(tái)程序文件 php java jsp
?表示運(yùn)行這個(gè)程序需要傳遞的參數(shù)
code=Android code是服務(wù)器端規(guī)定的字段
& 如果有多個(gè)參數(shù)使用&符號(hào)鏈接
4.ip地址、端口號(hào)
ip地址:唯一標(biāo)識(shí)某一臺(tái)電腦
端口號(hào):唯一標(biāo)識(shí)電腦上的某一個(gè)進(jìn)程(程序)80
數(shù)據(jù)傳輸:TCP/IP協(xié)議
TCP:面向連接的、安全的 打電話
UDP:面向無連接的 不安全 但快
5.網(wǎng)絡(luò)中的數(shù)據(jù)傳輸:
Socket實(shí)現(xiàn)->套接字
Socket類:客戶端
ServerSocket:服務(wù)器端
- 讀取數(shù)據(jù):服務(wù)器讀取 客戶端讀取
BufferedReader->InputStreamReader->socket.getInputStream() - 讀取終端
BufferedReader->InputStreamReader->System.in - 輸出:客戶端輸出 服務(wù)器端輸出
BufferedWriter->OutputStreamWriter->socket.getOutputStream()
PrintStream->socket.getOutputStream()
三、技術(shù)的使用
1.模擬客戶端
class Client{
public static void main(String[] args) throws IOException {
//1.創(chuàng)建用于通信的socket
// 指明和誰通信:ip地址 端口號(hào)
Socket socket=new Socket("127.0.0.1",8989);
// 接收服務(wù)器端的數(shù)據(jù)
BufferedReader br=new BufferedReader(new InputStreamReader(socket.getInputStream()));
//socket.getInputStream();
// 向服務(wù)器發(fā)送數(shù)據(jù)
//socket.getOutputStream();
String line=null;
while ((line=br.readLine())!=null){
System.out.println(line);
}
//客戶端向服務(wù)器端發(fā)送數(shù)據(jù)
PrintStream ps=new PrintStream(socket.getOutputStream());
ps.println("你好啊");
socket.shutdownOutput();
}
}
2.模擬服務(wù)器端
class Server{
public static void main(String[] args) throws IOException {
//1.創(chuàng)建服務(wù)器端的serversocket
ServerSocket ss=new ServerSocket(8989);
//2.獲取連接的客戶端的socket
Socket clientSocket=ss.accept();
//3.向客戶端發(fā)送數(shù)據(jù)
//BufferedWriter bw=new BufferedWriter(new OutputStreamWriter(clientSocket.getOutputStream()));
PrintStream ps=new PrintStream(clientSocket.getOutputStream());
ps.println("登錄成功");
//輸出完畢
clientSocket.shutdownOutput();
//4.服務(wù)器端接收客戶端發(fā)來的數(shù)據(jù)
BufferedReader br=new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
String line=null;
while ((line=br.readLine())!=null){
System.out.println(line);
}
}
}
3.實(shí)現(xiàn)上傳圖片
class Client{
public static void main(String[] args) throws IOException {
//連接服務(wù)器端 獲取socket
Socket socket=new Socket("127.0.0.1",8787);
//創(chuàng)建服務(wù)器端對(duì)應(yīng)的輸入流 用于接收服務(wù)器端發(fā)來的數(shù)據(jù)
BufferedReader br=new BufferedReader(new InputStreamReader(socket.getInputStream()));
System.out.println(br.readLine());
//向服務(wù)器端發(fā)送文件(圖片)
//1.將文件寫入到內(nèi)存
String path="C:\\Users\\asus\\Desktop\\草圖1.png";
FileInputStream fis=new FileInputStream(path);
//2.創(chuàng)建字節(jié)流
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 {
//創(chuàng)建服務(wù)器端的ServerSocket
ServerSocket ss=new ServerSocket(8787);
//監(jiān)聽客戶端連接
//當(dāng)有客戶端來連接這個(gè)服務(wù)器 就可以得到對(duì)應(yīng)的socket對(duì)象
//當(dāng)沒有客戶端來連接 服務(wù)器一直在這里等待
Socket socket=ss.accept();
//創(chuàng)建客戶端對(duì)應(yīng)的輸出流 用于向這個(gè)客戶端發(fā)送數(shù)據(jù)
PrintStream ps=new PrintStream(socket.getOutputStream());
ps.println("連接成功 可以輸出數(shù)據(jù)了!");
BufferedInputStream bis=new BufferedInputStream(socket.getInputStream());
//文件對(duì)應(yīng)的輸出流
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);
}
}
}
四、聊天功能的實(shí)現(xiàn)
1.對(duì)聊
(1)功能及實(shí)現(xiàn)方法
客戶端和服務(wù)器端都可以隨意地發(fā)送內(nèi)容
從終端輸入
- 客戶端:
主線程:接收終端輸入 將終端的輸入發(fā)送給服務(wù)器端
子線程:接收服務(wù)器端發(fā)來的數(shù)據(jù) - 服務(wù)器端:
主線程:接收終端輸入 將終端輸入發(fā)送給客服端
子線程:接收客戶端端發(fā)來的數(shù)據(jù)
(2)代碼實(shí)現(xiàn)
class Client{
public static void main(String[] args) throws IOException {
Socket socket=new Socket("127.0.0.1",9000);
//用一個(gè)子線程處理服務(wù)器端數(shù)據(jù)
new Thread(new ClientThread(socket)).start();
//主線程處理終端輸入 發(fā)送給服務(wù)器端
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);
}
}
}
/**
* 創(chuàng)建一個(gè)子線程處理客戶端接收服務(wù)器端數(shù)據(jù)
*
*/
class ClientThread implements Runnable{
private Socket socket;
//保存操作的socket對(duì)象
public ClientThread(Socket socket){
this.socket=socket;
}
@Override
public void run() {
BufferedReader br=null;
try {
//獲取服務(wù)器端的輸入流對(duì)象
br=new BufferedReader(new InputStreamReader(socket.getInputStream()));
//讀取數(shù)據(jù)
String line=null;
while ((line=br.readLine())!=null){
System.out.println(line);
}
} catch (IOException e) {
System.out.println("網(wǎng)絡(luò)出錯(cuò) 請(qǐng)重新登錄");
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();
//創(chuàng)建子線程 處理客戶端輸入信息
new ServerThread(socket).start();
//終端輸入流對(duì)象
BufferedReader keyin=new BufferedReader(new InputStreamReader(System.in));
//客戶端的輸出流對(duì)象
PrintStream ps=new PrintStream(socket.getOutputStream());
//讀取終端的輸入 將輸入輸出給客戶端
String line=null;
while ((line=keyin.readLine())!=null){
ps.println(line);
}
}
}
/**
* 創(chuàng)建一個(gè)子線程處理服務(wù)器端接收客戶端的數(shù)據(jù)
*/
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("網(wǎng)絡(luò)異常 請(qǐng)重新登錄");
System.exit(-1);
}finally {
//關(guān)閉輸入輸出流
//關(guān)閉對(duì)應(yīng)的socket鏈接
try {
if (br!=null){
br.close();
}
if (socket!=null){
socket.close();
}
}catch (IOException e){
e.printStackTrace();
}
}
}
}
2.群聊
(1)實(shí)現(xiàn)方法
在對(duì)聊的基礎(chǔ)上讓服務(wù)器端維護(hù)一個(gè)數(shù)組【socket】
(2)代碼實(shí)現(xiàn)
class Client{
public static void main(String[] args) throws IOException {
Socket socket=new Socket("10.129.28.253",6666);
//用一個(gè)子線程處理服務(wù)器端數(shù)據(jù)
new Thread(new ClientThread(socket)).start();
//主線程處理終端輸入 發(fā)送給服務(wù)器端
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);
}
}
}
/**
* 創(chuàng)建一個(gè)子線程處理客戶端接收服務(wù)器端數(shù)據(jù)
*
*/
class ClientThread implements Runnable{
private Socket socket;
//保存操作的socket對(duì)象
public ClientThread(Socket socket){
this.socket=socket;
}
@Override
public void run() {
BufferedReader br=null;
try {
//獲取服務(wù)器端的輸入流對(duì)象
br=new BufferedReader(new InputStreamReader(socket.getInputStream()));
//讀取數(shù)據(jù)
String line=null;
while ((line=br.readLine())!=null){
System.out.println(line);
}
} catch (IOException e) {
System.out.println("網(wǎng)絡(luò)出錯(cuò) 請(qǐng)重新登錄");
System.exit(-1);
}finally {
try {
if (br!=null){
br.close();
}
if (socket!=null){
socket.close();
}
}catch (IOException ex){
}
}
}
}
/**
* 1.如何實(shí)現(xiàn)群聊
* 在服務(wù)器端維護(hù)一個(gè)數(shù)組【socket】
* 2.私聊
* 3.給每個(gè)人起名字
*/
class Server{
//保存每一個(gè)鏈接過來的socket對(duì)象
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();
//當(dāng)有客戶端連接過來了 就保存
sockets.add(socket);
//開啟一個(gè)線程處理每一個(gè)客戶端的輸入
new ServerThread(socket).start();
}
}
}
/**
* 創(chuàng)建一個(gè)子線程處理服務(wù)器端接收客戶端的數(shù)據(jù)
*/
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){
//群發(fā)消息
//遍歷Server維護(hù)的數(shù)組
for (Socket s:Server.sockets){
//向socket對(duì)應(yīng)的客戶端發(fā)送消息
PrintStream ps=new PrintStream(s.getOutputStream());
ps.println(line);
}
}
} catch (IOException e) {
System.out.println("網(wǎng)絡(luò)異常 請(qǐng)重新登錄");
System.exit(-1);
}finally {
//關(guān)閉輸入輸出流
//關(guān)閉對(duì)應(yīng)的socket鏈接
try {
if (br!=null){
br.close();
}
if (socket!=null){
socket.close();
}
}catch (IOException e){
e.printStackTrace();
}
}
}
}