Java網絡編程(一)
***********************第15章 socket編程(網絡編程)************************
網絡編程 != 網站編程
京東 淘寶 網站編程
網絡
QQ----------------->QQ
一.為什麽使用socket
當兩個應用程序之間需要交換數據的時候 需要使用socket
QQ聊天或者傳文件
二.什麽是socket
插座的意思
在編程中socket翻譯成套接字
一組API,功能是用來解決兩個應用程序之間傳輸數據的問題..
套接字= ip地址 + 端口號
ip地址: 用來唯一的標示一臺主機
端口號: 用來唯一的標示一個進程... 占2個字節 2的16次方 65536種可能
TCP 65536 UDP 65536
****************************************TCP和UDP的區別*************************
1.TCP
傳輸控制協議 面向連接的 安全的 有順序的 就像打電話 QQ視頻用的是TCP
三次握手
2.UDP
用戶數據報協議 面向無連接的 不安全的 沒有順序 就像寫信一樣 CS QQ聊天發信息都使用的是UDP
*************************************如何使用socket************************************
現在寫的程序 都要寫兩個應用程序
服務器端的插座 ServerSocket
客戶端的插座 Socket
先寫服務器端、再寫客戶端
Socket的優點: 只要用戶建立好socket連接以後, socket技術就把兩個應用程序之間傳輸數據的問題
給你簡化成I/O操作了....
1.服務器端
Server.java
package com.chapter15;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
//服務器端
public class Server {
public static void main(String[] args) {
//TCP socket
//一.建立socket連接
//1.新建ServerSocket
ServerSocket ss = null;
Socket socket = null;
try {
ss = new ServerSocket(8888);
socket = ss.accept();//阻塞式 傻傻的等待
System.out.println("有一個客戶端連接");
} catch (IOException e) {
System.out.println("端口號已被占用");
e.printStackTrace();
}
//二.I/O操作
//三.關閉socket連接
if(socket!=null){
try {
socket.close();
} catch (IOException e) {
System.out.println("關閉socket失敗");
e.printStackTrace();
}
}
}
}
2.客戶端
Client.java
package com.chapter15;
import java.io.IOException;
import java.net.Socket;
import java.net.UnknownHostException;
//客戶端
public class Client {
public static void main(String[] args) {
// 一.建立socket連接
// 2.申請連接 相當於打電話的撥號
// 第一個參數 是要連接的服務器的ip地址
// 現在我要連接的是本地這臺機器 localhost 127.0.0.1--->真實的本機ip
Socket socket = null;
try {
socket = new Socket("localhost", 8888);// 系統會為客戶端的插座
// 隨機分配一個1024以上的端口號
} catch (UnknownHostException e) {
System.out.println("主機不存在");
e.printStackTrace();
} catch (IOException e) {
System.out.println("連接失敗");
e.printStackTrace();
}
// 二.I/O操作
// 三.關閉socket連接
if (socket != null) {
try {
socket.close();
} catch (IOException e) {
System.out.println("關閉socket失敗");
e.printStackTrace();
}
}
}
}
***************************************常見錯誤*******************************************
常見錯誤1:
端口號已被占用
java.net.BindException: Address already in use: JVM_Bind
at java.net.DualStackPlainSocketImpl.bind0(Native Method)
at java.net.DualStackPlainSocketImpl.socketBind(DualStackPlainSocketImpl.java:106)
at java.net.AbstractPlainSocketImpl.bind(AbstractPlainSocketImpl.java:382)
at java.net.PlainSocketImpl.bind(PlainSocketImpl.java:190)
at java.net.ServerSocket.bind(ServerSocket.java:375)
at java.net.ServerSocket.<init>(ServerSocket.java:237)
at java.net.ServerSocket.<init>(ServerSocket.java:128)
at com.chapter15.Server.main(Server.java:21)
說明已經有應用程序使用8888端口了,解決方案 把之前8888端口上的進程殺掉即可... 殺占用內存小的那個javaw
*************************************演示文件傳輸功能***********************************
原理: 兩次復制
************************************模擬QQ 實現1對1聊天************************
需求1: 客戶端給服務器說一句話: 你好,服務器
ok
需求2: 服務器 給客戶端 回一句 : 你壞,客戶端
java.net.SocketException: Socket is closed
at java.net.Socket.getOutputStream(Socket.java:943)
at com.chapter15.演示一對一聊天.Server.main(Server.java:74)
Exception in thread "main" java.lang.NullPointerException
at com.chapter15.演示一對一聊天.Server.main(Server.java:82)
Socket被關閉了,而且socket並沒有關閉 是在最後關閉的...
*********************************發生如下四種情況的時候會關閉socket連接**************************
1. 調用socket對象的close()方法 主動關閉socket
2. 如果關閉了socket中的 輸入流或輸出流關閉了,socket也自動關閉了
3. 應用程序結束後,socket也會自動關閉
4. Socket socket = new Socket();
Socket socket = null;
或
socket = new Socket();
socket對象置空,或者是讓這個socket對象的引用 引用一個新的socket對象 原來的socket對象就會變成垃圾,被垃圾
回收器進行回收,內存回收完以後,socket會關閉
剛才是由於把輸入流或輸出流關了,所以socket自動關閉了,解決方案,在服務器回復完以後 再關輸入流
*************************改完以後雖然不報SocketException了,但是阻塞了**************************
原因是BufferedReader 只有碰到\n的時候 才認為真正讀進來數據,解決方案 說話的時候 都要加一個\n
Java網絡編程(一)