網(wǎng)絡(luò)編程分為服務(wù)端和客戶(hù)端。服務(wù)端就相當(dāng)于我們平時(shí)說(shuō)的服務(wù)器斟叼,有固定的IP地址踱葛,隨時(shí)等待服務(wù)器連接并做出響應(yīng)丹莲;而客戶(hù)端相當(dāng)于各種端系統(tǒng),找到服務(wù)端進(jìn)行連接獲取服務(wù)尸诽。
IP地址:唯一標(biāo)識(shí)某一臺(tái)電腦
端口號(hào):唯一表示一臺(tái)電腦上的某一個(gè)進(jìn)程
網(wǎng)絡(luò)通信都是使用Socket來(lái)實(shí)現(xiàn)
創(chuàng)建一個(gè)客戶(hù)端的Socket服務(wù)甥材,在該對(duì)象建立時(shí)就可去連接指定主機(jī),因?yàn)門(mén)CP是面向連接的性含,所以在建立Socket服務(wù)時(shí)洲赵,就要有服務(wù)端存在,并連接成功,形成通路后叠萍,再通過(guò)該通道進(jìn)行數(shù)據(jù)的傳輸芝发。
下面寫(xiě)幾個(gè)簡(jiǎn)單的Demo
一.實(shí)現(xiàn)客戶(hù)端向服務(wù)端傳遞數(shù)據(jù)功能
我們先寫(xiě)客戶(hù)端
class Client{
public static void main(String[] args) throws IOException{
//1.創(chuàng)建用于通信的socket
// 指明和誰(shuí)通信:ip地址 端口號(hào)
Socket socket = new Socket("10.129.25.58",8989);
// 接收服務(wù)器端的數(shù)據(jù)
BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
// 向服務(wù)器端發(fā)送數(shù)據(jù)
//socket.getOutputStream();
//讀取服務(wù)器端發(fā)來(lái)的數(shù)據(jù)
String line = null;
while ((line = br.readLine()) != null){
System.out.println(line);
}
//客戶(hù)端向服務(wù)器端發(fā)送數(shù)據(jù)
PrintStream ps = new PrintStream(socket.getOutputStream());
ps.println("你好啊");
socket.shutdownOutput();
}
}
這里再簡(jiǎn)單提一下:
(1)字節(jié)操作流:OutputStream、InputStream苛谷;
(2)字符操作流:Writer辅鲸、Reader。
BufferedReader 由Reader類(lèi)擴(kuò)展而來(lái)抄腔,提供通用的緩沖方式文本讀取瓢湃,readLine讀取一個(gè)文本行,
從字符輸入流中讀取文本赫蛇,緩沖各個(gè)字符绵患,從而提供字符、數(shù)組和行的高效讀取悟耘。
BufferedWriter 由Writer 類(lèi)擴(kuò)展而來(lái)落蝙,提供通用的緩沖方式文本寫(xiě)入, newLine使用平臺(tái)自己的行分隔符暂幼,將文本寫(xiě)入字符輸出流筏勒,緩沖各個(gè)字符,從而提供單個(gè)字符旺嬉、數(shù)組和字符串的高效寫(xiě)入管行。
OutputStreamWriter:是Writer的子類(lèi),將輸出的字符流變?yōu)樽止?jié)流邪媳,即將一個(gè)字符流的輸出對(duì)象變?yōu)樽止?jié)流輸出對(duì)象捐顷。
InputStreamReader:是Reader的子類(lèi),將輸入的字節(jié)流變?yōu)樽址饔晷В磳⒁粋€(gè)字節(jié)流的輸入對(duì)象變?yōu)樽址鞯妮斎雽?duì)象迅涮。
以文件操作為例,內(nèi)存中的字符數(shù)據(jù)需要通過(guò)OutputStreamWriter變?yōu)樽止?jié)流才能保存在文件中徽龟,讀取時(shí)需要將讀入的字節(jié)流通過(guò)InputStreamReader變?yōu)樽址?/p>
然后再寫(xiě)服務(wù)器
class Server{
public static void main(String[] args) throws IOException{
//1.創(chuàng)建服務(wù)器端的ServerSocket
ServerSocket ss = new ServerSocket(8989);
//2.獲取連接的客戶(hù)端的socket
Socket clientSocket = ss.accept();
//3.向客戶(hù)端發(fā)送數(shù)據(jù)
//BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(clientSocket.getOutputStream()));
PrintStream ps = new PrintStream(clientSocket.getOutputStream());
ps.println("登陸成功");
//輸出完畢
clientSocket.shutdownOutput();
//4.接收客戶(hù)端發(fā)來(lái)的數(shù)據(jù)
BufferedReader br = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
String line = null;
while ((line = br.readLine()) != null){
System.out.println(line);
}
}
}
接下來(lái)我們?cè)倏匆幌逻\(yùn)行結(jié)果:
注意:先運(yùn)行服務(wù)器叮姑,再運(yùn)行客戶(hù)端
客戶(hù)端顯示了登錄成功
然后我們?cè)倏匆幌路?wù)器
上面這個(gè)Demo是很基礎(chǔ)的,所以在這個(gè)基礎(chǔ)上再加一丟丟難度据悔,也就是
二.實(shí)現(xiàn)服務(wù)器給客戶(hù)端發(fā)任意消息
class MyClient{
public static void main(String[] args){
//連接服務(wù)器端的socket
Socket socket = null;
try {
socket = new Socket("10.129.36.120",8080);
//接收服務(wù)器端信息
BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String line = null;
while ((line = br.readLine()) != null){
System.out.println(line);
}
//從鍵盤(pán)輸入數(shù)據(jù) 發(fā)送給服務(wù)器端
}catch (IOException e){
System.out.println("網(wǎng)絡(luò)出錯(cuò)传透,請(qǐng)重新登陸");
}finally {
//關(guān)閉連接
try {
socket.close();
}catch (IOException e){
e.printStackTrace();
}
}
}
}
class MyServer{
public static void main(String[] args){
//創(chuàng)建ServerSocket
try(ServerSocket ss = new ServerSocket(8080)) {
//監(jiān)聽(tīng)客戶(hù)端的連接
Socket socket = ss.accept();
//從終端接收數(shù)據(jù)
BufferedReader keyin = new BufferedReader(new InputStreamReader(System.in));
//獲取向客戶(hù)輸出數(shù)據(jù)的輸出流
PrintStream ps = new PrintStream(socket.getOutputStream());
String line = null;
while ((line = keyin.readLine()) != null){
//發(fā)送給客戶(hù)端
ps.println(line);
}
}catch (IOException e){
e.printStackTrace();
}
}
}
這時(shí)候我們運(yùn)行一下看結(jié)果
我們會(huì)看到兩邊都是空的 然后這時(shí)候我們?cè)诜?wù)器輸入想發(fā)送的內(nèi)容
輸入完內(nèi)容后記得要敲一下回車(chē)鍵
然后再看客戶(hù)端
ok內(nèi)容收到,功能實(shí)現(xiàn)屠尊。
我們做到了實(shí)現(xiàn)發(fā)消息旷祸,這時(shí)候會(huì)想怎么做一個(gè)能夠發(fā)圖片的,所以接下來(lái)我們?cè)僮鲆粋€(gè)實(shí)現(xiàn)給
二.服務(wù)器端發(fā)送圖片
class Client {
public static void main(String[] args) throws IOException {
//連接服務(wù)器 獲取socket
Socket socket = new Socket("10.129.36.120", 8080);
//創(chuàng)建服務(wù)器端對(duì)應(yīng)的輸入流 用于接收服務(wù)器端發(fā)來(lái)的數(shù)據(jù)
BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
System.out.println(br.readLine());
//向服務(wù)器端發(fā)送文件(圖片)
//1.將文件寫(xiě)入到內(nèi)存里
String path = "C:\\Users\\hp\\Desktop\\1.JPG";
FileInputStream fis = new FileInputStream(path);
//2.創(chuàng)建字節(jié)流 OutputStream
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(8080);
//監(jiān)聽(tīng)客戶(hù)端連接
//當(dāng)有客戶(hù)端來(lái)連接這個(gè)服務(wù)器 就可以得到對(duì)應(yīng)的socket
//當(dāng)沒(méi)有客戶(hù)端來(lái)連接 服務(wù)器一直在這里等待
Socket socket = ss.accept();
//創(chuàng)建客戶(hù)端對(duì)應(yīng)的輸出流 用于向這個(gè)客戶(hù)端發(fā)送數(shù)據(jù)
PrintStream ps = new PrintStream(socket.getOutputStream());
ps.println("連接成功 可以向我發(fā)數(shù)據(jù)了!");
//接收客戶(hù)端傳遞過(guò)來(lái)的圖片
BufferedInputStream bis = new BufferedInputStream(socket.getInputStream());
//文件對(duì)應(yīng)的輸出流
String path = "E:\\Java89\\app\\src\\main\\java\\java08212\\2.JPG";
FileOutputStream fos = new FileOutputStream(path);
byte[] buf = new byte[1024];
int len = -1;
while ((len = bis.read(buf)) != -1){
fos.write(buf,0,len);
}
}
}
接下來(lái)開(kāi)始運(yùn)行程序:
當(dāng)客戶(hù)端連接到服務(wù)器時(shí)讼昆,客戶(hù)端會(huì)收到一段提示:
然后服務(wù)器指定的位置會(huì)收到一張圖片:
圖片也發(fā)送成功了
最后我們?cè)賹?shí)現(xiàn)一個(gè)托享,兩人之間簡(jiǎn)單的聊天功能骚烧,上面我們做的都是單向的,客戶(hù)端向服務(wù)器發(fā)送消息闰围、圖片赃绊,所以我們要再實(shí)現(xiàn)
四.兩人之間互發(fā)消息
class Client{
public static void main(String[] args) throws IOException {
Socket socket = new Socket("10.129.36.120", 8080);
//用一個(gè)子線(xiàn)程處理服務(wù)器端數(shù)據(jù)
new Thread(new ClientThread(socket)).start();
//主線(xiàn)程處理終端輸入 發(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è)子線(xiàn)程處理客戶(hù)端接收服務(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(8080);
//獲取客戶(hù)端的socket
Socket socket = ss.accept();
new ServerThread(socket).start();
//終端輸入流對(duì)象
BufferedReader keyin = new BufferedReader(new InputStreamReader(System.in));
//客戶(hù)端的輸出流對(duì)象
PrintStream ps = new PrintStream(socket.getOutputStream());
//讀取終端的輸入 將輸入輸出給客戶(hù)端
String line = null;
while ((line = keyin.readLine()) != null){
ps.println(line);
}
}
}
/**
* 創(chuàng)建一個(gè)子線(xiàn)程處理服務(wù)器端接收客戶(hù)端的數(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){
}
}
}
}
運(yùn)行結(jié)果:
兩個(gè)人之間的簡(jiǎn)單的聊天功能已經(jīng)實(shí)現(xiàn)
那么,如何實(shí)現(xiàn)群聊功能呢羡榴?請(qǐng)看下回分解.....