java socket系列文章
java socket 单线程echo服务器
java socket 多线程echo服务器
java socket 线程池echo服务器
简单介绍socket
socket,通常也称作"套接字",用于描述IP地址和端口,是网络上运行的两个程序间双向通讯的一端,它既可以接受请求,也可以发送请求,利用它可以较为方便的编写网络上的数据的传递。
Socket通讯过程:服务端监听某个端口是否有连接请求,客户端向服务端发送连接请求,服务端收到连接请求向客户端发出接收消息,这样一个连接就建立起来了。客户端和服务端都可以相互发送消息与对方进行通讯。
socket编程中重要的方法:
- Accept方法用于产生”阻塞”,直到接受到一个连接,并且返回一个客户端的Socket对象实例。”阻塞”是一个术语,它使程序运行暂时”停留”在这个地方,直到一个会话产生,然后程序继续;通常”阻塞”是由循环产生的
- getInputStream方法获得网络连接输入,即一个输入流,同时返回一个IutputStream对象实例,客户端的Socket对象上的 getInputStream方法得到的输入流其实就是从服务器端发回的数据流;服务器端的输入流就是接受客户端发来的数据流。
- getOutputStream方法实现一个输出流,同时返回一个OutputStream对象实例。客户端的输出流就是将要发送到服务器端的数据流,服务器端的输出流就是发给客户端的数据流。
注意:
- getInputStream和getOutputStream方法均会产生一个IOException,它必须被捕获。
- getInputStream和getOutputStream方法返回的是流对象,通常都会被另一个流对象使用。所以还要对这两种方法获取的数据进行封装,以便更方便的使用。
如何开发一个Echo服务器
- 服务器,使用ServerSocket监听指定的端口,端口可以随意指定(由于1024以下的端口通常属于保留端口,在一些操作系统中不可以随意使用,所以建议使用大于1024的端口),等待客户连接请求,客户连接后,会话产生;在完成会话后,关闭连接。
- 客户端,使用Socket对网络上某一个服务器的某一个端口发出连接请求,一旦连接成功,打开会话;会话完成后,关闭Socket。
服务器端代码:
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.net.ServerSocket;
import java.net.Socket;
public class server {
public static void main(String[] args) throws Exception{
ServerSocket server = new ServerSocket(20011);
//服务端在20011端口监听客户端请求的TCP连接
Socket client = null;
boolean f = true;
while(f){
client = server.accept();
//服务端在调用accept()等待客户端的连接请求时会阻塞,直到收到客户端发送的连接请求才会继续往下执行代码
//链接成功后为每个客户端连接开始做出处理
try{
PrintStream out = new PrintStream(client.getOutputStream());
//获取Socket的输出流,用来向客户端发送数据
BufferedReader buf = new BufferedReader(new InputStreamReader(client.getInputStream()));
//获取Socket的输入流,用来接收从客户端发送过来的数据
boolean flag =true;
while(flag){
String str = buf.readLine();
//接收从客户端发送过来的数据
if(str == null || "".equals(str)){
flag = false;
}else{
if("bye".equals(str)){
flag = false;
}else{
//将接收到的字符串前面加上echo,发送到对应的客户端
out.println("echo:" + str);
}
}
}
out.close();
client.close();
}catch(Exception e){
e.printStackTrace();
}
}
server.close();
}
}
这个程序建立了一个服务器,它一直监听20011端口,等待用户连接。在建立连接后开始接受客户端传来的信息并再次将信息返回给客户端,当客户端输入“bye”时,结束会话。这个程序一次只能接受一个客户连接。
客户端代码:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.net.Socket;
import java.net.SocketTimeoutException;
public class client {
public static void main(String[] args) throws IOException {
Socket client = new Socket("127.0.0.1", 20011);
//客户端请求与本机在20011端口建立TCP连接
client.setSoTimeout(10000);
BufferedReader input = new BufferedReader(new InputStreamReader(System.in));
//获取键盘输入
PrintStream out = new PrintStream(client.getOutputStream());
//获取Socket的输出流,用来发送数据到服务端
BufferedReader buf = new BufferedReader(new InputStreamReader(client.getInputStream()));
//获取Socket的输入流,用来接收从服务端发送过来的数据
boolean flag = true;
while(flag){
System.out.print("输入信息:");
String str = input.readLine();
out.println(str);
//发送数据到服务端
if("bye".equals(str)){
flag = false;
}else{
try{
//从服务器端接收数据有个时间限制(系统自设,也可以自己设置),超过了这个时间,便会抛出该异常
String echo = buf.readLine();
System.out.println(echo);
}catch(SocketTimeoutException e){
System.out.println("Time out, No response");
}
}
}
input.close();
if(client != null){
//如果构造函数建立起了连接,则关闭套接字,如果没有建立起连接,自然不用关闭
client.close(); //只关闭socket,其关联的输入输出流也会被关闭
}
}
}
这个客户端连接到地址为1270.0.1的服务器,端口为20011,并从键盘输入一行信息,发送到服务器,然后接受服务器的返回信息。
Socket client = new Socket("127.0.0.1", 20011);
Socket实例代表了TCP连接的一个客户端,客户端请求与本机在20011端口建立TCP连接 ,127.0.0.1为IP地址。
client.setSoTimeout(10000);
表示如果对方连接状态10秒没有收到数据的话强制断开客户端。
BufferedReader input = new BufferedReader(new InputStreamReader(System.in));
获取键盘输入。
InputStreamReader 将字节流转换为字符流
BufferedReader,字符输入流中读取文本,缓冲各个字符,从而实现字符、数组和行的高效读取。
最后,首先运行server类,然后client类,然后在client的控制台输入任意字符,可以看到当输入bye是server和client都会退出。
运行结果,如图
此项目的完整代码可以到我的github,java-socket进行下载。