本文详细讲解socket的通信过程,便于理解,不对的地方请留言指出。
本片源于一篇中文字符乱码的讲解,请移步:
java socket通信时,中文字符乱码的一个解决方法 - mecho的专栏 - 博客频道 - CSDN.NET
点击打开链接
通信吗,就是双方收发消息,那么它具体怎么实现的呢?下面分析一下
先上代码:
服务端:
package helloword2;
import java.io.*;
import java.net.*;
public class HelloWord {
public static void main(String[] args) {
System.out.println("Server");
ServerSocket serverSocket = null;
Socket clientSocket = null;
int connects = 0;
try {
serverSocket = new ServerSocket(82, 5); //端口:82,最大链接数:5
//最多连接10次
while(connects < 10) {
connects++;
System.out.println("--------------------等待连接--------------------------");
clientSocket = serverSocket.accept(); //等待client连接
System.out.println("第 " + connects + " 次连接");
ServiceClient(clientSocket);
}
serverSocket.close();
} catch(IOException ioe) {
System.out.println("Error: " + ioe);
}
}
public static void ServiceClient(Socket client) throws IOException {
System.out.println("已链接");
InputStreamReader inSR = null;
OutputStreamWriter outSW = null;
try {
//读取数据
inSR = new InputStreamReader(client.getInputStream(), "UTF-8");
BufferedReader br = new BufferedReader(inSR);
outSW = new OutputStreamWriter(client.getOutputStream(), "UTF-8");
BufferedWriter bw = new BufferedWriter(outSW);
String str = "";
System.out.println("。。。。。有运行。。。");
while((str = br.readLine()) != null) {
//readLine()函数是阻塞的,链接建立后,等待消息输入,每次接受消息从这里开始执行,client中断即socket.close后就从while循环后面开始执行
str = str.trim();
// System.out.println("str==:" +br.readLine());
System.out.println("收到客户端消息:" + str);
bw.write("已收到信息:" + str + " \r\n"); //向客户端反馈消息,加上分行符以便客户端接收
bw.flush();
}
System.out.println("============服务器端====");
} finally {
//System.out.println("Cleaning up connection: " + client);
inSR.close();
outSW.close();
client.close();
System.out.println("*****服务端*************关闭流------" );
}
System.out.println("已断开");
}
}
说明:
运行服务端:run as Java Application
服务端运行到clientSocket = serverSocket.accept();阻塞函数,等待客户端链接
客户端代码:
package hellword3;
import java.io.*;
import java.net.*;
public class Example {
public static void main(String[] args) throws Exception{
System.out.println("Client");
try {
Socket clientSocket = new Socket("192.168.0.115", 82);
System.out.println("Client1:" + clientSocket);
DataInputStream dataIS = new DataInputStream(clientSocket.getInputStream());
InputStreamReader inSR = new InputStreamReader(dataIS, "UTF-8");
BufferedReader br = new BufferedReader(inSR);
DataOutputStream dataOS = new DataOutputStream(clientSocket.getOutputStream());
OutputStreamWriter outSW = new OutputStreamWriter(dataOS, "UTF-8");
BufferedWriter bw = new BufferedWriter(outSW);
//输入信息
byte bytes[] = new byte[100];
while(true) {
System.out.println("-----等待------输入--------");
System.in.read(bytes);
String str = new String(bytes);
str = str.trim();
if (str.equals("exit")) {
break;
}
//发送数据
bw.write(str + "\r\n"); //加上分行符,以便服务器按行读取
bw.flush();
//接收数据
while((str = br.readLine()) != null) {
str = str.trim();
System.out.println("服务器回复:" + str);
break;
}
System.out.println("===while 内------" );
}
inSR.close();
dataIS.close();
dataOS.close();
clientSocket.close();
System.out.println("========客户端==关闭流------" ); //while(true) 永远不会被执行吗?
} catch(UnknownHostException uhe) {
System.out.println("Error:" + uhe.getMessage());
} catch(ConnectException ce) {
System.out.println("Error:" + ce.getMessage());
} catch(IOException ioe) {
System.out.println("Error:" + ioe.getMessage());
} finally {
}
}
}
说明:
运行客户端:run as Java Application
这时,服务端输出:
服务端运行到while循环前等待客户端发来的消息。
客户端依次输入hello,你好,exit,输入时不要忘记回车
客户端l输出log:
服务器端输出:
解释:当链接建立后,服务器端消息是从这里开始运行的 while((str = br.readLine()) != null) { }一直循环,有消息就执行出来,
客户端输入exit时,客户端跳出while循环,执行 clientSocket.close(); 就是关闭socket流:
sever接到client端socket流关闭后,服务端也跳出while循环,
继续向下执行:
socket是端到端通信只要一端关了,另一端也自动关了,(任何一边关了,就都关了)线程不等待,会执行下去,顺序:
服务端开户—等待—链接—执行收发消息—往下执行。
解释一下:服务端运行后会等待客户端发来的socket请求链接:serverSocket.accept();链接建立以后,建立里流通道,等待客户端发来的消息: while((str = br.readLine()) != null),循环内会执行收发消息,socket.close以后,继续往下执行,及执行while后面的内容。直到执行完一次链接,等待下次:
注意:br.readLine()是阻塞函数(就是说它读完了一条信息在那等着,不往下执行), 要流关闭的时候 才会返回null,才会跳出循环,不然就等着,程序不往下走,这和QQ聊天时一个道理,你发一句,它接收一句,你不发,它就等着,你关闭QQ,它才关闭,往下执行,,另外其他流也可以收发消息,比如:发消息
DataOutputStream
output = new DataOutputStream(socket.getOutputStream());
output.writeUTF("send data");
PrintWriter
pw = new PrintWriter(socket.getOutputStream());// 要输出的数据流
pw.println(str);
pw.flush();
over。