一、socket实现读写
当我们想要在Java中使用TCP/IP通过网络连接到服务器时,就需要创建java.net.Socket对象并连接到服务器。假如希望使用Java NIO,也可以创建Java NIO中的SocketChannel对象。使用输出流在socket上发送数据,同时还可以使用输入流读取数据,不过打多数都为在客户端只能读取或只写入数据,而不是二者同时进行。最常见的模式是,客户端发送一个请求,然后服务器响应,客户端发送另外一个请求,服务器再做出响应,这个过程会继续直到客户端或服务器完成工作,然后关闭连接。
下面为客户端获取数据的一个例子:
<span style="font-family:Microsoft YaHei;"> /**
* 读取socket信息
* @param serverHost
* @author zzj
*/
public static void readSteam(String serverHost) {
Socket socket = null;
try {
socket = new Socket(serverHost,13);
//数据连接、读取操作时间
socket.setSoTimeout(1000*10);
InputStream inputStream = socket.getInputStream();
System.out.println("read stream..");
InputStreamReader reader = new InputStreamReader(inputStream);
StringBuffer sBuffer = new StringBuffer();
int a = 0;
for(a=reader.read();a!=-1;a=reader.read()){
sBuffer.append(a);
}
System.out.println(sBuffer);
} catch (Exception e) {
e.printStackTrace();
}finally{
if (socket!=null) {
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
</span>
<span style="font-family:Microsoft YaHei;"> /**
* 向服务器写数据
* @param serverHost socket服务器地址
* @param port 端口
* @author zzj
*/
public static void writeToServer(String serverHost,int port){
Socket socket = null;
try {
//创建并连接服务器
socket = new Socket(serverHost,port);
//设置操作超时时间30S
socket.setSoTimeout(1000*30);
//向服务器提交数据,需要使用输出流
OutputStream outputStream = socket.getOutputStream();
//为性能效率,把输出流串联到一个writer上
OutputStreamWriter writer = new OutputStreamWriter(outputStream,"utf-8");
writer.write("this is a client socket message!!!!");
//刷新输出,关闭流
writer.flush();
writer.close();
} catch (Exception e) {
e.printStackTrace();
}finally{
if (socket!=null) {
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}</span>
二、 半关闭连接
socket.close()方法可以同时关闭Socket的输入和输出。但是有时候可能只希望关闭连接的一般,即输入或者输出,那么可以使用shutdownInput/shutdownOutput方法可以只关闭连接的一半。这并不关闭socket,实际上他会调整与Socket连接的流,是他认为已经到了流的末尾,关闭输入之后在读取输入流会返回-1.关闭输出之后再写入Socket则会跑出一个IOException异常。下面为简单的代码实现:
<span style="font-family:Microsoft YaHei;">Socket socket = null;
try {
socket = new Socket(serverHost,13);
//数据连接、读取操作时间
socket.setSoTimeout(1000*10);
InputStream inputStream = socket.getInputStream();
System.out.println("read stream..");
InputStreamReader reader = new InputStreamReader(inputStream);
StringBuffer sBuffer = new StringBuffer();
int a = 0;
for(a=reader.read();a!=-1;a=reader.read()){
sBuffer.append(a);
}
//关闭输入流
socket.shutdownInput();
//下面使用输出流
OutputStream outputStream = socket.getOutputStream();
//....
System.out.println(sBuffer);
} catch (Exception e) {
e.printStackTrace();
}finally{
if (socket!=null) {
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}</span>
注意,即使输入和输出的关闭方法都关闭了,仍然需要调用close进行流的关闭,因为shutdown只影响流,而不影响socket的连接资源,如所占用的端口不会释放。另外可以通过isInputShutdown,isOutputShutdown等方法来确定是否关闭了输入输出流等。
Socket类是java完成其他TCP操作的基础类,如Url类,UrlConncetion,HttpUrlConnection等类最终都会调用这个方法来实现数据传输 这类使用原生代码与注解操作系统的本地tcp栈进行通信。