java.lang.Object
|——java.net.Socket
和Datagramdsocket并没有继承关系
1、面向连接
请求——响应
Request——Response
2、Socket编程
服务器和客户端之间的双向管道就叫Socket,
一个连接对应一个Socket,站在服务器还是客户端都是对应这一条Socket
不同连接建立不同的Socket
1、 服务端 ServerSocket
先启动服务器再连接
- 创建服务器 指定端口 ServerSocket(int port) <1024以下留给系统使用>
- 接受客户端的连接 阻塞式 accept()
- 发送数据 接收数据
new BufferedWriter(new OutputStreamReader(< Socket >.getOutputStream(……)))
2、客户端 Socket
- 创建客户端 必须指定服务端+端口 自己的端口是系统自动分配的 Socket
- 接受数据 getInputStream
多个客户端_聊天室原理
为每一个连接建立一个线程
聊天室:中转站
- 客户端可以发送数据 接受数据
- 服务端为每一个客户端创建一个线程
……
阶段一:
服务端
public class Server {
public static void main(String[] args) throws IOException {
ServerSocket server = new ServerSocket(8888);
//阻塞接收消息
Socket socket = server.accept();
System.out.println("already builded");
String msg = "welcome to use";
BufferedWriter bw = new BufferedWriter(
new OutputStreamWriter(
socket.getOutputStream()));
bw.write(msg);
bw.newLine();
bw.flush();
}
}
客户端
public static void main(String[] args) throws UnknownHostException, IOException {
Socket client = new Socket("localhost",8888);
BufferedReader br = new BufferedReader(
new InputStreamReader(
client.getInputStream()));
String echo = br.readLine();
System.out.println(echo);
}
阶段二:返回控制台输入的字符
服务端
public static void main(String[] args) throws UnknownHostException, IOException {
ServerSocket server = new ServerSocket(7777);
Socket client = server.accept();
DataInputStream dis = new DataInputStream(client.getInputStream());
String msg = dis.readUTF();
System.out.println(msg);
DataOutputStream dos = new DataOutputStream(client.getOutputStream());
dos.writeUTF("server-->"+msg);
dos.flush();
server.close();
}
客户端
public static void main(String[] args) throws UnknownHostException, IOException {
Socket client = new Socket("localhost",7777);
BufferedReader console = new BufferedReader(new InputStreamReader(System.in));
String info = console.readLine();
DataOutputStream dos = new DataOutputStream(client.getOutputStream());
dos.writeUTF(info);
dos.flush();
DataInputStream dis = new DataInputStream(client.getInputStream());
String msg = dis.readUTF();
System.out.println(msg);
client.close();
}
阶段三:引入线程
CloseAll.java
public class CloseUtil {
public static void closeAll(Closeable... io) {
for(Closeable temp:io) {
try {
if(null!=temp) {
temp.close();
}
} catch (IOException e) {
}
}
}
}
Send.java
public class Send implements Runnable{
//控制台输入流
private BufferedReader console;
//管道输出流
private DataOutputStream dos;
//运行的标识
private boolean isRunning = true;
public Send() {
console = new BufferedReader(new InputStreamReader(System.in));
}
public Send(Socket client) {
this();
try {
dos = new DataOutputStream(client.getOutputStream());
} catch (IOException e) {
isRunning=false;
CloseUtil.closeAll(dos, console);
}
}
private String getMsgFromConsole() {
try {
return console.readLine();
} catch (IOException e) {
}
return "";
}
public void send() {
String msg = getMsgFromConsole();
try {
if(null!=msg && !msg.equals("")) {
dos.writeUTF(msg);
dos.flush();
}
} catch (IOException e) {
isRunning =false;
CloseUtil.closeAll(dos, console);
}
}
@Override
public void run() {
//线程体
while(isRunning) {
send();
}
}
}
Receive.java
public class Receive implements Runnable{
private DataInputStream dis;
private boolean isRunning = true;
public Receive() {
}
public Receive(Socket client) {
try {
dis= new DataInputStream(client.getInputStream());
} catch (IOException e) {
isRunning =false;
CloseUtil.closeAll(dis);
}
}
public String receive() {
String msg="";
try {
msg = dis.readUTF();
} catch (IOException e) {
isRunning =false;
CloseUtil.closeAll(dis);
}
return msg;
}
@Override
public void run() {
//线程体
while(isRunning) {
System.out.println(receive());
}
}
}
Client.java
public class Client {
public static void main(String[] args) throws UnknownHostException, IOException {
Socket client = new Socket("localhost",7777);
new Thread(new Send(client)).start();
new Thread(new Receive(client)).start();
}
}
Server.java
public class Server {
public static void main(String[] args) throws UnknownHostException, IOException {
ServerSocket server = new ServerSocket(7777);
Socket client = server.accept();
DataInputStream dis = new DataInputStream(client.getInputStream());
DataOutputStream dos = new DataOutputStream(client.getOutputStream());
System.out.println("i get");
while(true) {
String msg = dis.readUTF();
System.out.println(msg);
dos.writeUTF("server-->"+msg);
dos.flush();
}
}
}
阶段四:群聊
Server
public class Server {
private List<MyChannel> all = new ArrayList<MyChannel>();
/**
* @param args
* @throws IOException
*/
public static void main(String[] args) throws IOException {
new Server().start();
}
public void start() throws IOException{
ServerSocket server =new ServerSocket(9999);
while(true){
Socket client =server.accept();
MyChannel channel = new MyChannel(client);
all.add(channel);//统一管理
new Thread(channel).start(); //一条道路
}
}
/**
* 一个客户端 一条道路
* 1、输入流
* 2、输出流
* 3、接收数据
* 4、发送数据
* @author Administrator
*
*/
private class MyChannel implements Runnable{
private DataInputStream dis ;
private DataOutputStream dos ;
private boolean isRunning =true;
public MyChannel(Socket client ) {
try {
dis = new DataInputStream(client.getInputStream());
dos = new DataOutputStream(client.getOutputStream());
} catch (IOException e) {
//e.printStackTrace();
CloseUtil.closeAll(dis,dos);
isRunning =false;
}
}
/**
* 读取数据
* @return
*/
private String receive(){
String msg ="";
try {
msg=dis.readUTF();
} catch (IOException e) {
//e.printStackTrace();
CloseUtil.closeAll(dis);
isRunning =false;
all.remove(this); //移除自身
}
return msg;
}
/**
* 发送数据
*/
private void send(String msg){
if(null==msg ||msg.equals("")){
return ;
}
try {
dos.writeUTF(msg);
dos.flush();
} catch (IOException e) {
//e.printStackTrace();
CloseUtil.closeAll(dos);
isRunning =false;
all.remove(this); //移除自身
}
}
/**
* 发送给其他客户端
*/
private void sendOthers(){
String msg = this.receive();
//遍历容器
for(MyChannel other:all){
if(other ==this){
continue;
}
//发送其他客户端
other.send(msg);
}
}
@Override
public void run() {
while(isRunning){
sendOthers();
}
}
}
}