1.socket通信
Socket原理机制:
1.通信的两端都有Socket
2.网络通信其实就是Socket间的通信
3.数据在两个Socket间通过IO传输
socket和serverSocket通信简单介绍如下,注意客户端与服务器端是怎么交换数据的:
应用多线程实现服务器与多客户端之间的通信:
① 服务器端创建ServerSocket,循环调用accept()等待客户端连接
② 客户端创建一个socket并请求和服务器端连接
③ 服务器端接受请求,创建socket与该客户建立专线连接
④ 建立连接的两个socket在一个单独的线程上对话
⑤ 服务器端继续等待新的连接
2.服务器端代码
package com.tl.skyLine.socket;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
/**
* 聊天 服务器端
* Created by tl on 17/3/1.
*/
public class ChatServer {
private int port = 8080;// 默认服务器端口
public ChatServer() {
}
// 创建指定端口的服务器
public ChatServer(int port) {
this.port = port;
}
// 提供服务
public void service() {
int i = 0;
try {
// 建立服务器连接,设定客户连接请求队列的长度
ServerSocket server = new ServerSocket(port, 3);
while (true) {
// 等待客户连接
Socket socket = server.accept();
i++;
System.out.println("第" + i + "个客户连接成功!");
new Thread(new ServerThread(socket, i)).start();
}
} catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
new ChatServer().service();
}
}
class ServerThread implements Runnable {
private int index;
private Socket socket;
public ServerThread(Socket socket, int i) {
this.socket = socket;
this.index = i;
}
// 任务是为一个用户提供服务
@Override
public void run() {
try {
try {
// 读取客户端传过来信息的DataInputStream
DataInputStream in = new DataInputStream(socket
.getInputStream());
// 向客户端发送信息的DataOutputStream
DataOutputStream out = new DataOutputStream(socket
.getOutputStream());
while (true) {
// 读取来自客户端的信息
String accpet = in.readUTF();
System.out.println("第" + index + "个客户端发出消息:" + accpet);
}
} finally {// 建立连接失败的话不会执行socket.close();
socket.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
3.客户端代码
package com.tl.skyLine.socket;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;
import java.util.Random;
import java.util.Scanner;
/**
* 聊天 客户端
* Created by tl on 17/3/1.
*/
public class ChatClient {
private String host = "localhost";// 默认连接到本机
private int port = 8080;// 默认连接到端口8080
private String name = String.valueOf(new Random().nextInt(999999));//客户端的名字
public ChatClient() {
}
// 连接到指定的主机和端口
public ChatClient(String host, int port) {
this.host = host;
this.port = port;
}
public void chat() {
try {
// 连接到服务器
Socket socket = new Socket(host, port);
// 设置超时
// Socket s = new Socket();
// SocketAddress socketAddress = new InetSocketAddress(serverIp, port);
// s.connect(socketAddress, timeout);
try {
// 读取服务器端传过来信息的DataInputStream
DataInputStream in = new DataInputStream(socket
.getInputStream());
// 向服务器端发送信息的DataOutputStream
DataOutputStream out = new DataOutputStream(socket
.getOutputStream());
// 装饰标准输入流,用于从控制台输入
Scanner scanner = new Scanner(System.in);
while (true) {
String send = scanner.nextLine();
// 把从控制台得到的信息传送给服务器
out.writeUTF("客户端[" + name + "]:" + send);
// 读取来自服务器的信息
String accpet = in.readUTF();
System.out.println(accpet);
}
} finally {
socket.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
new ChatClient().chat();
}
}
以上代码利用Socket对象和ServerSocket对象进行简单的网络交互,即客户端通过DataOutputStream对象的writeUTF()方法向服务器发送消息,服务器利用DataInputStream对象的readUTF()方法读出数据。其中ServerSocket对象的accept()方法是阻塞的方法,它会一直等待,直到有客户端连接,同理,DataInputStream对象的readUTF()方法也是阻塞的方法,它也会一直等待,直到客户端调用writeUTF()方法。
上面代码中ChatClient.java中,客户端控制台发送信息之后,String accpet = in.readUTF();将会一直阻塞,如果是单线程的话,重新开一个客户端,也是处于阻塞当中,所以将服务端设置为多线程,这样就不会影响下一个客户端的通信。
4.运行结果: