在Socket编程时,记住要先启动服务器,后启动客户端。
主要使用的类:
- Socket() 创建一个未连接的套接字,并使用系统默认类型的SocketImpl
- Socket(InetAddress address,int port) 创建流套接字并将连接到指定的IP地址的指定端口号
- InetAddress getInetAddress() 返回套接字所连接的地址
- InputStream getInputStream() 返回此套接字的输入流
- OutputStream getOutputStream() 返回此套接字的输出流
int getPort() 返回此套接字连接到的远程端口号
实现了服务器套接字。服务器套接字等待通过网络进入的请求。它根据该请求执行一些操作,然后将结果返回给请求者。
- ServerSocket() 创建未绑定的服务器套接字
- ServerSocket(int port) 创建绑定到指定端口的服务器套接字
- Socket accept() 监听套连接到此套接字并接收它
- int getLocalPort() 返回此套接字正在监听的端口号
- 创建ServerSocket对象,绑定监听端口
- 通过accept()方法监听客户端请求
- 连接建立后,通过输入流读取客户端发送的请求信息
- 通过输出流向客户端发送响应信息
public class Server {
public static void main(String[] args) {
//1.创建一个服务器端的ServerSocket,指定绑定的端口
try {
ServerSocket serverSocket=new ServerSocket(8888);
//2.调用accept()开始监听,等待客户端的连接
System.out.println("***服务器即将启动,等待客户端的连接***");
Socket socket=serverSocket.accept();
//3.获取输入流,读取客户端信息
InputStream is=socket.getInputStream();
InputStreamReader isr=new InputStreamReader(is);
BufferedReader br=new BufferedReader(isr);
String data=null;
while((data=br.readLine())!=null) {
System.out.println("服务器:"+data);
}
socket.shutdownInput();
//4.获取输出流,响应客户端的请求
OutputStream os=socket.getOutputStream();
PrintWriter pw=new PrintWriter(os);
pw.write("欢迎您");
pw.flush();
//5.关闭各种资源
pw.close();
os.close();
br.close();
isr.close();
is.close();
socket.close();
serverSocket.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
1.创建Socket对象,指明需要连接的服务器的地址和端口号
2.连接建立后,通过输出流向服务器端发送请求信息
3.通过输入流获取服务器响应的信息
4.关闭相关资源
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();
InputStreamReader isr=new InputStreamReader(is);
BufferedReader br=new BufferedReader(isr);
String data=null;
while((data=br.readLine())!=null) {
System.out.println("客户端:"+data);
}
socket.shutdownInput();
//4.关闭资源
br.close();
isr.close();
is.close();
pw.close();
os.close();
socket.close();
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
客户端保持不变,只需修改服务器端代码。
public class ServerThread extends Thread {
Socket socket=null;
public ServerThread(Socket socket) {
this.socket=socket;
}
//线程执行的操作,响应客户端的请求
public void run(){
InputStream is=null;
PrintWriter pw=null;
OutputStream os=null;
BufferedReader br=null;
InputStreamReader isr=null;
try {
is = socket.getInputStream();
isr=new InputStreamReader(is);
br=new BufferedReader(isr);
String data=null;
while((data=br.readLine())!=null) {
System.out.println("服务器:"+data);
}
socket.shutdownInput();
//4.获取输出流,响应客户端的请求
os=socket.getOutputStream();
pw=new PrintWriter(os);
pw.write("欢迎您");
pw.flush();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally {
try {
//5.关闭各种资源
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();
}
}
}
}
public class Server {
public static void main(String[] args) {
//1.创建一个服务器端的ServerSocket,指定绑定的端口
try {
int count=0; //客户端数量
ServerSocket serverSocket=new ServerSocket(8888);
//2.调用accept()开始监听,等待客户端的连接
System.out.println("***服务器即将启动,等待客户端的连接***");
Socket socket=null;
while(true) {
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();
}
}
}
在使用多线程的时候,一定要注意优先级的设置!!!
对于同一个socket,如果关闭了输出流,则与该输出流关联的socket也会被关闭,所以一般不用关闭流,直接关闭socket即可。
用于发送和接收数据报数据包的套接字。
- DatagramSocket() 构造数据报套接字并将其绑定到本地主机上的任何可用端口。
- DatagramSocket(int port) 构造数据报套接字并将其绑定到本地主机上的指定端口
- void receive(DatagramPacket p) 从此套接字接收数据报包
- void send(DatagramPacket p) 从此套接字发送数据报包
- void setSoTimeout(int timeout) 以指定的超时(以毫秒为单位)启动/禁用SO_TIMEOUT
- DatagramPacket(byte[] buf,int length) 构造一个DatagramPacket用于接收length长度的数据包。
- DatagramPacket(byte[] buf,int length,InetAddress address,int port) 构造用于发送length长度的分组的数据报,指定主机上到指定的端口号。
- InetAddress getAddress() 返回该数据报发送或接受数据报的计算机的IP地址。
- byte[] getData() 返回数据缓冲区。
- int getLength() 返回要发送的数据的长度或接收到的数据的长度。
- int getPort() 返回发送数据报的远程主机上的端口号,或从中接收数据报的端口号。
- 创建DatagramSocket,指定端口号
- 创建DatagramPacket
- 接收客户端发送的数据信息
- 读取信息
public class server {
public static void main(String[] args) throws IOException {
//1.创建服务器段DatagramSocket,并指定端口
DatagramSocket socket=new DatagramSocket(8800);
System.out.println("***服务器端已启动,等待客户端连接***");
//2.创建数据报,用于接收客户端发送的数据
byte[] data=new byte[1024];
DatagramPacket packet=new DatagramPacket(data,data.length);
//3.接收客户端发送的数据
socket.receive(packet); //此方法在接收到数据报之前会一直阻塞
//4.读取数据
String info=new String(data,0,packet.getLength());
System.out.println("服务器:"+info);
/*
* 向客户端响应数据
*/
//1.定义客户端的地址,端口,数据
InetAddress address=packet.getAddress();
int port=packet.getPort();
byte[] data2="欢迎您! ".getBytes();
//2.创建数据报,包含响应的数据信息
DatagramPacket packet2=new DatagramPacket(data2,data2.length,address,port);
//3.相同客户端
socket.send(packet2);
//关闭资源
socket.close();
}
}
- 定义发送信息
- 创建DatagramPacket,包含将要发送的信息
- 创建DatagramPacket
- 发送数据
public class client {
public static void main(String[] args) throws IOException {
//1.定义服务器的地址,端口号,数据
InetAddress address=InetAddress.getByName("localhost");
int port=8800;
byte[] data="用户名:admin;密码:123".getBytes();
//2.创建数据报,包含发送的数据信息
DatagramPacket packet=new DatagramPacket(data,data.length,address,port);
//3.创建DatagramSocket对象
DatagramSocket socket=new DatagramSocket();
//4.向服务器端发送数据报
socket.send(packet);
/*
* 接收服务端响应的数据
*/
byte[] data2=new byte[1024];
DatagramPacket packet2=new DatagramPacket(data2,data2.length);
socket.receive(packet2);
String reply=new String(data2,0,packet2.getLength());
System.out.println("客户端:"+reply);
socket.close();
}
}
public class ServerThread extends Thread {
DatagramSocket socket=null;
DatagramPacket packet=null;
public ServerThread(DatagramSocket socket,DatagramPacket packet) {
this.socket=socket;
this.packet=packet;
}
public void run() {
//4.读取数据
String info=new String(packet.getData(),0,packet.getLength());
System.out.println("服务器:"+info);
/*
* 向客户端响应数据
*/
//1.定义客户端的地址,端口,数据
InetAddress address=packet.getAddress();
int port=packet.getPort();
byte[] data2="欢迎您! ".getBytes();
//2.创建数据报,包含响应的数据信息
DatagramPacket packet2=new DatagramPacket(data2,data2.length,address,port);
//3.相同客户端
try {
socket.send(packet2);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public class server {
public static void main(String[] args) throws IOException {
//1.创建服务器段DatagramSocket,并指定端口
int count=0;
DatagramSocket socket=new DatagramSocket(8800);
System.out.println("***服务器端已启动,等待客户端连接***");
while(true) {
//2.创建数据报,用于接收客户端发送的数据
byte[] data=new byte[1024];
DatagramPacket packet=new DatagramPacket(data,data.length);
//3.接收客户端发送的数据
socket.receive(packet); //此方法在接收到数据报之前会一直阻塞
ServerThread servletThread=new ServerThread(socket,packet);
servletThread.setPriority(4);
servletThread.start();
count++;
System.out.println("客户端数量:"+count);
}
}
}