Java基础教程:网络编程
基础
Socket与ServerSocket
Socket又称"套接字",网络上的两个程序通过一个双向的通信连接实现数据的交换,这个连接的一端称为一个socket。
ServerSocket,此类实现服务器套接字。服务器套接字等待通过网络传入的请求然后基于该请求执行某些操作,可能向请求者返回结果。
Socket方法 getInetAddress(); //远程服务端的IP地址
getPort(); //远程服务端的端口
getLocalAddress() //本地客户端的IP地址
getLocalPort() //本地客户端的端口
getInputStream(); //获得输入流
getOutStream(); //获得输出流 Socket状态
isClosed(); //连接是否已关闭,若关闭,返回true;否则返回false
isConnect(); //如果曾经连接过,返回true;否则返回false
isBound(); //如果Socket已经与本地一个端口绑定,返回true;否则返回false
说明:两者本质均是Socket间的通信,一方为客户,另一方为服务器。客户连接服务器,服务器接受客户并生成一个与其交流的Socket,然后客户发送请求,服务器做出响应。
Socket与ServerSocket的交互
连接超时问题及策略
1.从套接字读取信息时,在有数据可供访问之前,读操作会被阻塞。
解决:对于不同的应用应该设置合理的超时值。
socket.setSoTimeout(10000);
说明:设置超时值后,如果没有在规定时间内接受到数据,就会抛出SocketTimeOutException异常。你可以捕获这个异常并做出反应。
2.客户端在连接到服务器之前会一直堵塞。
解决:可以先构造一个无连接的套接字,然后再使用一个超时来进行连接的方法解决这个问题。
Socket socket = new Socket("127.0.0.1",12345);
//用下面方法代替上面方法
Socket socket1 = new Socket();
socket1.connect(new InetSocketAddress("127.0.0.1",12345),timeout);
实例
客户端代码
开启Socket
如果在客户端,你需要写下如下的代码就可以打开一个socket。
String host = "127.0.0.1";
int port = 8919;
Socket client = new Socket(host, port);
上面代码中,host即客户端需要连接的机器,port就是服务器端用来监听请求的端口。在选择端口时,需要注意一点,就是0~1023这些端口都已经被系统预留了。这些端口为一些常用的服务所使用,比如邮件,FTP和HTTP。当你在编写服务器端的代码,选择端口时,请选择一个大于1023的端口。
写入数据
接下来就是写入请求数据,我们从客户端的socket对象中得到OutputStream对象,然后写入数据后。很类似文件IO的处理代码。
public class ClientSocket {
public static void main(String args[]) {
String host = "127.0.0.1";
int port = 8919;
try {
Socket client = new Socket(host, port);
Writer writer = new OutputStreamWriter(client.getOutputStream());
writer.write("Hello From Client");
writer.flush();
writer.close();
client.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
关闭IO对象
类似文件IO,在读写数据完成后,我们需要对IO对象进行关闭,以确保资源的正确释放。
服务器代码
打开服务器端的socket
int port = 8919;
ServerSocket server = new ServerSocket(port);
Socket socket = server.accept();
上面的代码创建了一个服务器端的socket,然后调用accept方法监听并获取客户端的请求socket。accept方法是一个阻塞方法,在服务器端与客户端之间建立联系之前会一直等待阻塞。
读取数据
通过上面得到的socket对象获取InputStream对象,然后安装文件IO一样读取数据即可。这里我们将内容打印出来。
public class ServerClient {
public static void main(String[] args) {
int port = 8919;
try {
ServerSocket server = new ServerSocket(port);
Socket socket = server.accept();
Reader reader = new InputStreamReader(socket.getInputStream());
char chars[] = new char[1024];
int len;
StringBuilder builder = new StringBuilder();
while ((len=reader.read(chars)) != -1) {
builder.append(new String(chars, 0, len));
}
System.out.println("Receive from client message=: " + builder);
reader.close();
socket.close();
server.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
关闭IO对象
还是不能忘记的,最后需要正确地关闭IO对象,以确保资源的正确释放。
总结
进行客户端-服务器端编程还是比较有趣的,同时在Java中进行socket编程要比其他语言(如C)要简单快速编写。java.net这个包里面包含了很多强大灵活的类供开发者进行网络编程,在进行网络编程中,建议使用这个包下面的API。同时Sun.*这个包也包含了很多的网络编程相关的类,但是不建议使用这个包下面的API,因为这个包可能会改变,另外这个包不能保证在所有的平台都有包含。