java 客戶端與服務端通信
1、網絡通信
網絡通信是通過網絡將各個孤立的設備進行連接,通過信息交換實現人與人,人與計算機,計算機與計算機之間的通信。
要素:
- ip
- 端口【1024~49151程序註冊接口】
- 協議
* TCP:用戶傳輸協議、可靠連接、三次握手四次分手【打電話】
* UDP:用戶數據報協議、不可靠不穩定連接【發短信】
另,本地的進程間通信方式:
- 消息傳遞(管道、FIFO、消息隊列)
- 同步(互斥量、條件變量、讀寫鎖、文件和寫記錄鎖、信號量)
- 共享內存
- 遠程過程調用
2、socket
- 提供一組函數接口
- 套接字(socket)是一個抽象層,應用程序可以通過它發送或接收數據,可對其進行像對文件一樣的打開、讀寫和關閉等操作。
- 套接字允許應用程序將I/O插入到網絡中,並與網絡中的其他應用程序進行通信。
- 網絡套接字是IP地址與端口的組合。套接字Socket=(IP地址:端口號)
3、基於TCP協議的通信過程
一:客戶端向服務端發送信息
ps:一次性的!且僅是客戶端向服務器端發送
服務器
- ServerSocket類
- ServerSocket是等待客戶端的請求,一旦獲得一個連接請求,就創建一個Socket示例來與客戶端進行通信。
- 服務器端的Socket對象是通過accept()方法得到的
package com.study.socket;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;
public class Server_ {
public static void main(String[] args) throws IOException {
//1、設一個地址
ServerSocket socket = null;
//2、等待客戶端連接
Socket accept = null;
//3、讀取客戶端消息
InputStream is = null;
/*
byte[] buff = new byte[1024];
int len;
while(len=is.read(buff) != -1){
String msg = new String(buff,0,len);
}
*/
//4、管道流
ByteArrayOutputStream os=null;
try {
socket = new ServerSocket(1025);
accept = socket.accept();
is = accept.getInputStream();
os = new ByteArrayOutputStream();
byte[] buff = new byte[1024];
int len;
while((len=is.read(buff)) != -1){
os.write(buff,0,len);
}
System.out.println(os.toString());
} catch (IOException e) {
e.printStackTrace();
} finally {
os.close();
is.close();
socket.close();
accept.close();
}
}
}
客戶端
- Socket類
- 一旦成功創建一個Socket類的實例,可以用它來發送和接收字節流
package com.study.socket;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Scanner;
public class Client_ {
public static void main(String[] args) throws IOException {
while(true) {
//1、服務器的地址
InetAddress addr = null;
int port = 1025;
//2、創建一個socket連接
Socket socket = null;
//3、發送消息
OutputStream os = null;
Scanner in = new Scanner(System.in);
InputStream is = null;
try {
addr = InetAddress.getByName("127.0.0.1");
socket = new Socket(addr, port);
os = socket.getOutputStream();
// is = socket.getInputStream();
// byte[] buff = new byte[1024];
// int len;
// while ((len = is.read(buff)) != -1) {
// os.write(buff, 0, len);
// }
System.out.print("客戶端:");
String msg_send = in.next();
os.write(msg_send.getBytes());
} catch (IOException e) {
e.printStackTrace();
} finally {
os.close();
socket.close();
}
}
}
}
效果
二:雙方通信
ps:一次發送多條信息,對方無法一次性全接收到!
服務器端
package com.study.socket;
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
public class Server {
public static void main(String[] args) throws IOException {
System.out.println("服務器啓動!!!!");
try {
//創建服務器,並開放10000端口
ServerSocket server = new ServerSocket(10000);
while(true){
//從連接隊列中取出一個連接,如果沒有則等待
Socket socket = server.accept();
//啓動線程
new Thread(new ToClientDialog(socket)).start();
System.out.println("客戶端連接成功 地址: "+socket.getInetAddress()+" 端口::"+socket.getPort());//½ÓÊպͷ¢ËÍÊý¾Ý
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
package com.study.socket;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.text.SimpleDateFormat;
import java.util.Date;
public class ToClientDialog implements Runnable{
private Socket dialogSocket = null;
public ToClientDialog() {
super();
}
//初始化
public ToClientDialog(Socket socket){
dialogSocket = socket;
}
public void run() {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
if (dialogSocket != null) {
BufferedReader in;
PrintWriter out;
try {
//接收
in = new BufferedReader(new InputStreamReader(dialogSocket.getInputStream()));
//輸出
out = new PrintWriter(dialogSocket.getOutputStream(), true);
//獲取用戶輸入
BufferedReader line = new BufferedReader(new InputStreamReader(
System.in));
while(true){
//接收客戶端發送來的數據
String msg = in.readLine();
if (msg.equals("end")) {
break;
}
System.out.println(sdf.format(new Date()) + " client:" + msg);
//向客戶端發送用戶輸入的數據
out.println(line.readLine());
}
line.close();
out.close();
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
客戶端
package com.study.socket;
import java.io.*;
import java.net.Socket;
import java.net.UnknownHostException;
public class Client {
public static void main(String[] args) throws IOException {
System.out.println("客戶端啓動!!!");
Socket socket;
try {
//連接主機地址
socket = new Socket("127.0.0.1", 10000);
//啓動
new Thread(new ToServiceDialog(socket)).start();
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
package com.study.socket;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.text.SimpleDateFormat;
import java.util.Date;
public class ToServiceDialog implements Runnable {
private Socket dialogSocket = null;
public ToServiceDialog(){
}
//初始化
public ToServiceDialog(Socket socket){
dialogSocket = socket;
System.out.println("連接"+socket.getInetAddress().getHostName()+"主機成功");
}
public void run() {
BufferedReader in;
PrintWriter out;
BufferedReader line;
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
if (dialogSocket != null) {
try {
//接收
in = new BufferedReader(new InputStreamReader(
dialogSocket.getInputStream()));
//輸出
out = new PrintWriter(dialogSocket.getOutputStream(), true);
//獲取用戶輸入
line = new BufferedReader(new InputStreamReader(
System.in));
while(true){
//接受控制檯輸入的數據
String sendMsg = line.readLine();
//向服務端發送數據
out.println(sendMsg);
if (sendMsg.equals("end")) {
break;
}
//接收服務端發送來的數據
String msg = in.readLine();
System.out.println(sdf.format(new Date()) + " service: " + msg);
}
line.close();
out.close();
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
效果
三:利用別人優秀的的即時通信框架
- 騰訊
- openfire
- goEasy
- …