1. 程式人生 > >java基礎----網路程式設計 tcp

java基礎----網路程式設計 tcp

package cn.itcast.tcp;


import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;


/*
 
 UDP通訊協議的特點:
1. 將資料極封裝為資料包,面向無連線。
2. 每個資料包大小限制在64K中
3.因為無連線,所以不可靠
4. 因為不需要建立連線,所以速度快
5.udp 通訊是不分服務端與客戶端的,只分傳送端與接收端。


TCP通訊協議特點:
1. tcp是基於IO流進行資料 的傳輸 的,面向連線。
  2. tcp進行資料傳輸的時候是沒有大小限制的。
  3. tcp是面向連線,通過三次握手的機制保證資料的完整性。 可靠協議。
  4. tcp是面向連線的,所以速度慢。
  5. tcp是區分客戶端與服務端 的。
 
  比如: 打電話、 QQ\feiQ的檔案傳輸、 迅雷下載.... 
 
tcp協議下的Socket:
Socket(客戶端) , tcp的客戶端一旦啟動馬上要與服務端進行連線。
ServerSocket(服務端類)


tcp的客戶端使用步驟:
1. 建立tcp的客戶端服務。
2. 獲取到對應的流物件。
3.寫出或讀取資料
4. 關閉資源。




 */


//tcp客戶端
public class Demo1Client {

public static void main(String[] args) throws IOException{
//建立tcp的服務
Socket socket  = new Socket(InetAddress.getLocalHost(),9090);
//獲取到Socket的輸出流物件
OutputStream outputStream = socket.getOutputStream();
//利用輸出流物件把資料寫出即可。
outputStream.write("服務端你好".getBytes());

//獲取到輸入流物件,讀取服務端回送的資料。
InputStream inputStream = socket.getInputStream();
byte[] buf = new byte[1024];
int length = inputStream.read(buf);
System.out.println("客戶端接收到的資料:"+ new String(buf,0,length));

//關閉資源
socket.close();
}
}


package cn.itcast.tcp;



import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;


//tcp的服務端
/*
java.net.BindException:   埠被佔用。


ServerSocket的使用 步驟
1. 建立tcp服務端 的服務。
2. 接受客戶端的連線產生一個Socket.
3. 獲取對應的流物件讀取或者寫出資料。
4. 關閉資源。




為什麼ServerSocket不設計一個getInputStream與getOutputStream 呢? 


*/
//服務端
public class Demo1Server {


public static void main(String[] args) throws Exception {
//建立Tcp的服務端,並且監聽一個埠。
ServerSocket serverSocket = new ServerSocket(9090);
//接受客戶端的連線
Socket socket  =  serverSocket.accept(); //accept()  接受客戶端的連線 該方法也是一個阻塞型的方法,沒有客戶端與其連線時,會一直等待下去。
//獲取輸入流物件,讀取客戶端傳送的內容。
InputStream inputStream = socket.getInputStream();
byte[] buf = new byte[1024];
int length = 0;
length = inputStream.read(buf);
System.out.println("服務端接收:"+ new String(buf,0,length));

//獲取socket輸出流物件,向客戶端傳送資料
OutputStream outputStream = socket.getOutputStream();
outputStream.write("客戶端你好啊!".getBytes());


//關閉資源
serverSocket.close();

}

}



package cn.itcast.tcp;


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.InetAddress;
import java.net.Socket;


/*
 需求: 客戶端與服務端一問一答聊天。
 
 
 1.如果使用BuffrerdReader的readline方法一定要加上\r\n才把資料寫出。
 2.使用字元流一定要呼叫flush方法資料才會寫出。
 
 */




//聊天的客戶端
public class ChatClient {


public static void main(String[] args) throws IOException {
//建立tcp的客戶端服務
Socket socket = new Socket(InetAddress.getLocalHost(),9090);
//獲取socket的輸出流物件。
OutputStreamWriter socketOut =new OutputStreamWriter(socket.getOutputStream());
//獲取socket的輸入流物件
BufferedReader socketReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));

//獲取鍵盤的輸入流物件,讀取資料
BufferedReader keyReader = new BufferedReader(new InputStreamReader(System.in));

String line = null;
//不斷的讀取鍵盤錄入的資料,然後把資料寫出
while((line = keyReader.readLine())!=null){
socketOut.write(line+"\r\n");
//重新整理
socketOut.flush();

//讀取服務端回送的資料
line = socketReader.readLine();
System.out.println("服務端回送的資料是:"+line);
}
//關閉資源
socket.close();
}


}





package cn.itcast.tcp;


import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;


//tcp的服務端
/*
java.net.BindException:   埠被佔用。


ServerSocket的使用 步驟
1. 建立tcp服務端 的服務。
2. 接受客戶端的連線產生一個Socket.
3. 獲取對應的流物件讀取或者寫出資料。
4. 關閉資源。




為什麼ServerSocket不設計一個getInputStream與getOutputStream 呢? 


*/
//服務端
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.ServerSocket;
import java.net.Socket;


/*
 聊天的服務端
 
 
 瀏覽器與伺服器之間的資料傳輸就是使用了Tcp協議通訊的的
 */
public class ChatServer {


public static void main(String[] args) throws IOException {
//建立tcp的服務端
ServerSocket serverSocket = new ServerSocket(9090);
//接受客戶端的連線,產生一個Socket
Socket socket = serverSocket.accept();
//獲取到Socket的輸入流物件
BufferedReader socketReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));

//獲取到Socket輸出流物件
OutputStreamWriter socketOut =  new OutputStreamWriter(socket.getOutputStream());

//獲取鍵盤的輸入流物件
BufferedReader keyReader = new BufferedReader(new InputStreamReader(System.in));


//讀取客戶端的資料
String line = null;
while((line = socketReader.readLine())!=null){
System.out.println("服務端接收到的資料:"+ line);

System.out.println("請輸入回送給客戶端的資料:");
line = keyReader.readLine();
socketOut.write(line+"\r\n");
socketOut.flush();
}

//關閉資源
serverSocket.close();
}

}




package cn.itcast.tcp;
import java.io.IOException;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;


//模擬Tomcat伺服器
public class TomcatDemo extends Thread {

Socket socket;

public TomcatDemo(Socket socket){
this.socket = socket;
}


public void run() {
try {
//獲取socket的輸出流物件
OutputStream outputStream = socket.getOutputStream();
//把資料寫到瀏覽器上
outputStream.write("<html><head><title>aaa</title></head><body>你好啊瀏覽器</body></html>".getBytes());
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}



public static void main(String[] args) throws IOException {
//建立tcp的服務端
ServerSocket serverSocket = new ServerSocket(9090);
//不斷的接受客戶端的連線
while(true){
Socket socket = serverSocket.accept();
new TomcatDemo(socket).start();
}
}

}





多執行緒下載圖片



package cn.itcast.tcp;


import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.HashSet;


/*
1. 編寫一個服務端可以給多個客戶端傳送圖片。 (多執行緒)


*/
public class ImageServer extends Thread {

Socket socket ;

//使用該集合是用於儲存ip地址的。
static HashSet<String> ips = new HashSet<String>();

public  ImageServer(Socket socket) {
this.socket = socket;
}

@Override
public void run() {
try {
//獲取到socket輸出流物件
OutputStream outputStream = socket.getOutputStream();
//獲取圖片的輸入流物件
FileInputStream fileInputStream = new FileInputStream("F:\\美女\\3.jpg");
//讀取圖片資料,把資料寫出
byte[] buf = new byte[1024];
int length = 0 ; 
while((length = fileInputStream.read(buf))!=-1){

outputStream.write(buf,0,length);
}
String ip = socket.getInetAddress().getHostAddress();   // socket.getInetAddress() 獲取對方的IP地址
if(ips.add(ip)){
System.out.println("恭喜"+ip+"同學成功下載,當前下載的人數是:"+ ips.size());
}



//關閉資源
fileInputStream.close();
socket.close();
}catch (IOException e) {

}
}


public static void main(String[] args) throws IOException {
//建立tcp的服務 ,並且要監聽一個埠
ServerSocket serverSocket  = new ServerSocket(9090);
while(true){
//接受使用者的連結。
Socket socket = serverSocket.accept();
new ImageServer(socket).start();

}
}


}


package cn.itcast.tcp;


import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;


//下載圖片的客戶端
public class ImageClient {


public static void main(String[] args) throws Exception{
//建立tcp的服務
Socket socket = new Socket(InetAddress.getLocalHost(),9090);
//獲取socket的輸入流物件
InputStream inputStream = socket.getInputStream();
//獲取檔案的輸出流物件
FileOutputStream fileOutputStream = new FileOutputStream("F:\\3.jpg");
//邊讀邊寫
byte[] buf = new byte[1024];
int length = 0 ; 
while((length = inputStream.read(buf))!=-1){
fileOutputStream.write(buf,0,length);
}
//關閉資源
fileOutputStream.close();
socket.close();

}

}




多使用者登入


package cn.itcast.tcp;


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.InetAddress;
import java.net.Socket;




/*
2.  實現登陸與註冊 功能。  
客戶端與服務端連線的時候,就要提示客戶端請選擇功能。

客戶端註冊的時候,使用者名稱與密碼都是傳送給服務端 的,服務端需要把資料儲存到服務端的檔案上。

登陸: 登陸的時候客戶端輸入使用者名稱與密碼傳送給服務端,服務端需要校驗,返回結果給客戶端。
*/


public class LoginClient {

public static void main(String[] args) throws IOException {
Socket socket = new Socket(InetAddress.getLocalHost(),9090);
//獲取socket的輸出流物件
OutputStreamWriter  socketOut = new OutputStreamWriter(socket.getOutputStream());

//獲取到socket的輸入流物件
BufferedReader socketReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));

//獲取到鍵盤的輸入流物件
BufferedReader keyReader = new BufferedReader(new InputStreamReader(System.in));
while(true){
System.out.println("請選擇功能: A(登陸)  B(註冊)");
String option = keyReader.readLine();
if("a".equalsIgnoreCase(option)){
getInfo(socketOut, keyReader, option);
//讀取伺服器反饋的資訊
String line = socketReader.readLine();
System.out.println(line);
}else if("b".equalsIgnoreCase(option)){
getInfo(socketOut, keyReader, option);
//讀取伺服器反饋的資訊
String line = socketReader.readLine();
System.out.println(line);
}


}


}


public static void getInfo(OutputStreamWriter  socketOut,BufferedReader keyReader, String option)
throws IOException {
System.out.println("請輸入使用者名稱:");
String userName = keyReader.readLine();
System.out.println("請輸入密碼:");
String password = keyReader.readLine();
String info = option +" "+userName+" "+password+"\r\n";
socketOut.write(info);
socketOut.flush();
}

}




package cn.itcast.tcp;


import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Properties;


public class LoginServer extends Thread {


Socket socket;


static File file = new File("F:\\users.properties");


public LoginServer(Socket socket) {
this.socket = socket;
}


static {
try {
if (!file.exists()) {
file.createNewFile();
}
} catch (IOException e) {
e.printStackTrace();
}


}


@Override
public void run() {
while(true){

try {
// 獲取socket的輸入流物件
BufferedReader bufferedReader = new BufferedReader(
new InputStreamReader(socket.getInputStream()));
// 獲取socket的輸出流物件
OutputStreamWriter socketOut = new OutputStreamWriter(
socket.getOutputStream());

// 讀取客戶端輸入的資訊
String info = bufferedReader.readLine();
String[] datas = info.split(" ");
// 獲取到使用者 的選擇功能
String option = datas[0];
// 註冊
String userName = datas[1];

String password = datas[2];

if ("a".equalsIgnoreCase(option)) {
// 登陸
Properties properties = new Properties();
// 載入配置檔案
properties.load(new FileReader(file));
if (properties.containsKey(userName)) {
String tempPass = properties.getProperty(userName);
if (password.equals(tempPass)) {
socketOut.write("歡迎" + userName + "登陸成功\r\n");

} else {
socketOut.write("密碼錯誤\r\n");
}

} else {
socketOut.write("使用者名稱不存在,請重新輸入...\r\n");
}

socketOut.flush();

} else if ("b".equalsIgnoreCase(option)) {

// 建立一個配置檔案類
Properties properties = new Properties();
//載入原來的配置檔案
properties.load(new FileReader(file));
if (!properties.containsKey(userName)) {
// 不存在該使用者名稱
properties.setProperty(userName, password);
// 生成一個配置檔案
properties.store(new FileWriter(file), "users");
socketOut.write("註冊成功..\r\n");
} else {
// 存在使用者名稱
socketOut.write("使用者名稱已經被註冊,請重新輸入\r\n");
}
socketOut.flush();
}
} catch (Exception e) {
e.printStackTrace();
}
}


}


public static void main(String[] args) throws IOException {
ServerSocket serverSocket = new ServerSocket(9090);
while (true) {
Socket socket = serverSocket.accept();
new LoginServer(socket).start();
}


}


}