参考博客:http://blog.youkuaiyun.com/x_and_y/article/details/53067450
Socket通信
ip地址和端口组成了Socket。
Socket与ServerSocket的交互,下面的图片我觉得已经说的很详细很清楚了。
服务器端:ServerSocket类
客户端:Socket类
1、Socket通信实现步骤
(1)创建ServerSocket和Socket
(2)打开连接到Socket的输入输出流
(3)按照协议对Socket进行读写操作
(4)关闭输入输出流,关闭Socket
2、服务器端
(1)创建ServerSocket对象,绑定监听端口
(2)通过accept()方法监听客户端请求
(3)连接建立后,通过输入流读取客户端发送的请求信息
(4)通过输出流向客户端发送响应信息
(5)关闭相关资源
3、客户端
(1)创建Socket对象,指明需要连接的服务器的地址和端口
(2)连接建立后,通过输入流向服务器发送请求信息
(3)通过输出流获取服务器响应的信息
(4)关闭相关资源
4、套接字:
客户端和服务器之间要进行通信首先要建立连接,然后才能在这个连接上收发字节流。
套接字就是连接的一个端点,每个套接字都有一个套接字地址,由32位整数IP地址和16位整数端口号组成,用“IP地址:端口号”表示。这就好比要在宿舍楼找到一个人,不仅要知道他的楼栋号(IP),还要知道房间号(端口)。
一个连接由两端的套接字地址唯一确定,称为套接字对。
(client address: client port, server address: server port)
其中客户端的端口是临时分配的端口,服务器的端口是固定的知名端口。
Java中的服务器套接字是ServerSocket,客户端套接字是socket。两者建立连接后,就能通过输入输出流进行通信了(服务器的输入流对应客户端的输出流,服务器的输出流对应客户端的输入流)。
5、Socket和ServerSocket的常用方法
(1)Socket常用方法摘要
构造方法摘要
常用方法摘要
(2)ServerSocket
构造方法类
常用方法类
6、经典的例子
多线程服务器:
应用多线程来实现服务器与多客户端之间的通信
(1)服务器端
package test;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
public class Server {
public static void main(String[] args) {
try {
//1、创建服务器端Socket,即ServerSocket
//指定绑定的端口,并监听此端口
ServerSocket serverSocket=new ServerSocket(8888);
Socket socket=null;
//记录客户端数量
int count=0;
//2、调用accept()方法开始监听,等待客户端的连接
System.out.println("***服务器即将启动,等待客户端的连接***");
//循环监听等待客户端的连接
while(true){
//调用accept()方法开始监听,等待客户端的连接
socket=serverSocket.accept();
//创建一个新的线程
ServerThread serverThread=new ServerThread(socket);
//启动线程
serverThread.setPriority(4);
serverThread.start();
count++;
System.out.println("客户端数量:"+count);
InetAddress address=socket.getInetAddress();
System.out.println("当前客户端的ip:"+address.getHostAddress());
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
(2)服务器线程处理类
package test;
/*
* 服务器线程处理类
*/
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.Socket;
public class ServerThread extends Thread {
//和本线程相关的socket
Socket socket=null;
public ServerThread(Socket socket){
this.socket=socket;
}
//线程执行的操作,响应客户端的请求
public void run(){
InputStream is=null;
//将字节流转换为字符流
InputStreamReader isr=null;
//为输入流添加缓冲
BufferedReader br=null;
OutputStream os=null;
//包装为打印流
PrintWriter pw=null;
try {
is = socket.getInputStream();
isr = new InputStreamReader(is);
br = new BufferedReader(isr);
String info=null;
while((info=br.readLine())!=null){
//循环读取客户端的信息
System.out.println("我是服务器,客户端说"+info);
}
socket.shutdownInput();
os = socket.getOutputStream();
pw = new PrintWriter(os);
pw.write("欢迎您");
pw.flush();//调用flush()方法,将缓冲输出
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally {
//5、关闭资源
try {
if(pw!=null){
pw.close();
}
if(os!=null){
os.close();
}
if(br!=null){
br.close();
}
if(isr!=null){
isr.close();
}
if(is!=null){
is.close();
}
if(socket!=null){
socket.close();
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
(3)客户端类
package test;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.Socket;
public class Client {
public static void main(String[] args) {
try {
//1、创建客户端socket,指定服务器地址和端口
Socket socket=new Socket("localhost", 8888);
//2、获取输出流,向服务器端发送信息
OutputStream os=socket.getOutputStream();//字节输出流
PrintWriter pw=new PrintWriter(os);//将输出流包装为打印流
pw.write("用户名:admin;密码:123");
pw.flush();
socket.shutdownOutput();
//3、获取输入流,用来读取服务器端的响应信息
InputStream is=socket.getInputStream();
BufferedReader br=new BufferedReader(new InputStreamReader(is));
String info=null;
while((info=br.readLine())!=null){
System.out.println("我是客户端,服务器说"+info);
}
//4、关闭资源
br.close();
is.close();
// pw.close();
os.close();
socket.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
InetAddress
InetAddress 类提供将主机名解析为其 IP 地址(或反之)的方法。