1. 基本通信架構
資料封包長度不受限制。
- Client端
System.out.println("-----Client-----");
//1、建立連接配接: 使用Socket建立用戶端 + 服務的位址和端口
Socket client =new Socket("localhost",8888); //目标位址及端口
//2、操作: 輸入輸出流操作
DataOutputStream dos =new DataOutputStream(client.getOutputStream());
String data ="hello"; //無需\r\n,自動加上
dos.writeUTF(data);
dos.flush();
//3、釋放資源
dos.close();
client.close();
- Server端
System.out.println("-----Server-----");
// 1、指定端口 使用ServerSocket建立伺服器
ServerSocket server =new ServerSocket(8888); //指定伺服器偵聽的端口
// 2、阻塞式等待連接配接 accept
Socket client =server.accept(); //用戶端一連上就取消阻塞
System.out.println("一個用戶端建立了連接配接");
// 3、操作: 輸入輸出流操作
DataInputStream dis =new DataInputStream(client.getInputStream());
String data =dis.readUTF();
System.out.println(data);
// 4、釋放資源
dis.close();
client.close();
server.close();
2. 雙向通信
- 用戶端
public class LoginTwoWayClient {
public static void main(String[] args) throws UnknownHostException, IOException {
System.out.println("-----Client-----");
BufferedReader console =new BufferedReader(new InputStreamReader(System.in));
System.out.print("請輸入使用者名:");
String uname =console.readLine();
System.out.print("請輸入密碼:");
String upwd =console.readLine();
//1、建立連接配接: 使用Socket建立用戶端 +服務的位址和端口
Socket client =new Socket("localhost",8888);
//2、操作: 輸入輸出流操作
DataOutputStream dos =new DataOutputStream(client.getOutputStream());
dos.writeUTF("uname="+uname+"&"+"upwd="+upwd);
dos.flush();
DataInputStream dis =new DataInputStream(client.getInputStream());
String result =dis.readUTF();
System.out.println(result);
//3、釋放資源
dos.close();
client.close();
}
}
- 伺服器端
public class LoginTwoWayServer {
public static void main(String[] args) throws IOException {
System.out.println("-----Server-----");
// 1、指定端口 使用ServerSocket建立伺服器
ServerSocket server =new ServerSocket(8888);
// 2、阻塞式等待連接配接 accept
Socket client =server.accept(); //用戶端一連上就取消阻塞
System.out.println("一個用戶端建立了連接配接");
// 3、操作: 輸入輸出流操作
DataInputStream dis =new DataInputStream(client.getInputStream());
String datas =dis.readUTF();
String uname ="";
String upwd ="";
//分析
String[] dataArray = datas.split("&");
for(String info:dataArray) {
String[] userInfo =info.split("=");
if(userInfo[0].equals("uname")) {
System.out.println("你的使用者名為:"+userInfo[1]);
uname = userInfo[1];
}else if(userInfo[0].equals("upwd")) {
System.out.println("你的密碼為:"+userInfo[1]);
upwd = userInfo[1];
}
}
//輸出
DataOutputStream dos =new DataOutputStream(client.getOutputStream());
if(uname.equals("bee") && upwd.equals("123456")) { //成功
dos.writeUTF("登入成功,歡迎回來");
}else { //失敗
dos.writeUTF("使用者名或密碼錯誤");
}
dos.flush();
// 4、釋放資源
dis.close();
client.close();
server.close();
}
}
3. 檔案傳輸(對檔案大小沒有限制)
- 用戶端上傳檔案
System.out.println("-----Client-----");
//1、建立連接配接: 使用Socket建立用戶端 +服務的位址和端口
Socket client =new Socket("localhost",8888); //目标位址及目标端口
//2、操作: 拷貝 上傳
InputStream is =new BufferedInputStream(new FileInputStream("src/foo.png"));
OutputStream os =new BufferedOutputStream(client.getOutputStream());
byte[] flush =new byte[1024];
int len = -1;
while((len=is.read(flush))!=-1) {
os.write(flush,0,len);
}
os.flush();
//3、釋放資源
os.close();
is.close();
client.close();
- 服務端接收檔案
System.out.println("-----Server-----");
// 1、指定端口 使用ServerSocket建立伺服器
ServerSocket server =new ServerSocket(8888);
// 2、阻塞式等待連接配接 accept
Socket client =server.accept(); //用戶端一連上就取消阻塞
System.out.println("一個用戶端建立了連接配接");
// 3、操作: 檔案拷貝 存儲
InputStream is =new BufferedInputStream(client.getInputStream());
OutputStream os =new BufferedOutputStream(new FileOutputStream("src/oof.png"));
byte[] flush =new byte[1024];
int len = -1;
while((len=is.read(flush))!=-1) {
os.write(flush,0,len);
}
os.flush();
//3、釋放資源
os.close();
is.close();
// 4、釋放資源
client.close();
server.close();
4. TCP多重連接配接
- 伺服器端
public class LoginMultiServer {
public static void main(String[] args) throws IOException {
System.out.println("-----Server-----");
// 1、指定端口 使用ServerSocket建立伺服器
ServerSocket server =new ServerSocket(8888);
boolean isRunning =true;
// 2、阻塞式等待連接配接 accept
while(isRunning) {
Socket client =server.accept(); //用戶端一連上就取消阻塞
System.out.println("一個用戶端建立了連接配接");
new Thread(new Channel(client)).start();
}
server.close();
}
//一個channel就代表一個用戶端
static class Channel implements Runnable{
private Socket client;
//輸入流
private DataInputStream dis;
//輸出流
private DataOutputStream dos;
public Channel(Socket client) {
this.client = client;
try {
//輸入
dis = new DataInputStream(client.getInputStream());
//輸出
dos =new DataOutputStream(client.getOutputStream());
} catch (IOException e) {
e.printStackTrace();
release();
}
}
//接收資料
private String receive() {
String datas ="";
try {
datas = dis.readUTF();
} catch (IOException e) {
e.printStackTrace();
}
return datas;
}
//釋放資源
private void release() {
// 4、釋放資源
try {
if(null != dos) {
dos.close();
}
} catch (IOException e) {
e.printStackTrace();
}
try {
if(null != dis) {
dis.close();
}
} catch (IOException e) {
e.printStackTrace();
}
try {
if(null != client) {
client.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
//發送資料
private void send(String msg) {
try {
dos.writeUTF(msg);
dos.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void run() {
// 3、操作: 輸入輸出流操作
String uname ="";
String upwd ="";
//分析
String[] dataArray = receive().split("&");
for(String info:dataArray) {
String[] userInfo =info.split("=");
if(userInfo[0].equals("uname")) {
System.out.println("你的使用者名為:"+userInfo[1]);
uname = userInfo[1];
}else if(userInfo[0].equals("upwd")) {
System.out.println("你的密碼為:"+userInfo[1]);
upwd = userInfo[1];
}
}
if(uname.equals("bee") && upwd.equals("123456")) { //成功
send("登入成功,歡迎回來");
}else { //失敗
send("使用者名或密碼錯誤");
}
release();
}
}
}
- 用戶端
public class LoginMultiClient {
public static void main(String[] args) throws UnknownHostException, IOException {
System.out.println("-----Client-----");
//1、建立連接配接: 使用Socket建立用戶端 +服務的位址和端口
Socket client =new Socket("localhost",8888);
//2、操作: 輸入輸出流操作 先請求後響應
new Send(client).send();
new Receive(client).receive();
client.close();
}
//發送
static class Send{
private Socket client;
private DataOutputStream dos;
private BufferedReader console ;
private String msg;
public Send(Socket client) {
console=new BufferedReader(new InputStreamReader(System.in));
this.msg =init();
this.client = client;
try {
dos=new DataOutputStream(client.getOutputStream());
} catch (IOException e) {
e.printStackTrace();
}
}
private String init() {
try {
System.out.print("請輸入使用者名:");
String uname =console.readLine();
System.out.print("請輸入密碼:");
String upwd =console.readLine();
return "uname="+uname+"&"+"upwd="+upwd;
} catch (IOException e) {
e.printStackTrace();
}
return "";
}
public void send() {
try {
dos.writeUTF(msg);
dos.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
}
//接收
static class Receive{
private Socket client;
private DataInputStream dis;
public Receive(Socket client) {
this.client = client;
try {
dis=new DataInputStream(client.getInputStream());
} catch (IOException e) {
e.printStackTrace();
}
}
public void receive() {
String result;
try {
result = dis.readUTF();
System.out.println(result);
} catch (IOException e) {
e.printStackTrace();
}
}
}
}