看了几天TCP/IP协议和HTTP协议后,自己写了一个Demo用socket实现了一下(PC做服务器,Android做客户端),果然不动手不知道有些细节得注意。遇到最大的问题就是遇到这个异常java.net.SocketException: socket is closed
单向传输数据的时候server与client是没有问题的,但是两个都有输入输出操作的时候就出现了上面这个问题。一般来说,流 得在finally中关闭,像out.close();bufferedReader.close();如果这样做就会出现上面的异常。
异常主要出现在socket.getOutputStream()或socket.getInputStream(),按照我的理解:bufferReader.close()与out.close()关闭会直接导致sockect。所以解决方法是:将out.close()与bufferReader.close()换成socket.shutdownOutput()与socket.shutdownInput(),就不会出现Socket直接被关闭的问题了。
shutdownInput()和close()的区别:shutdownInput和shutdownOutput没有关闭网络连接的功能,仅关闭输入流或仅关闭输出流。而close()方法还会将socket连接给关闭掉。
服务器端:
主要代码:
1.ServerSocket serverSocket = new ServerSocket(1989); //创建一个ServerSocket对象,并让这个Socket在1989端口监听
2.在While循环中,Socket socket=serverSocket.accept();//接受客户端所发送的请求。如果客户端没有发送数据,那么该线程就停滞不继续
3.在子线程中,socket.getOutputStream() ;或socket.getInputStream() ;//获取输入流来读取客户端内容和获取输出流来发送数据给客户端。如果用到缓冲,记得flush();
package pack;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStreamWriter;
import java.net.ServerSocket;
import java.net.Socket;
public class SocketDemo {
public static void main(String[] args) throws IOException{
ServerSocket serverSocket = null;
// 创建一个ServerSocket对象,并让这个Socket在1989端口监听
serverSocket = new ServerSocket(1989);
// 调用ServerSocket的accept()方法,接受客户端所发送的请求,
// 如果客户端没有发送数据,那么该线程就停滞不继续
while (true) {
//等待客户端连接
Socket socket = serverSocket.accept();
if(socket!=null)
new SocketThread(socket).start();
new SocketThread2(socket).start();
}
}
}
class SocketThread extends Thread{
Socket socket=null;
public SocketThread(Socket socket){
this.socket=socket;
}
public void run(){
InputStream inputStream=null;
try{
// 从Socket当中得到InputStream对象 ,读取客户端所发送的数据
inputStream = socket.getInputStream();
byte buffer[] = new byte[1024];
int temp = 0;
while ((temp = inputStream.read(buffer)) != -1) {
System.out.println(new String(buffer, 0, temp));
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
class SocketThread2 extends Thread{
Socket socket=null;
public SocketThread2(Socket socket){
this.socket=socket;
}
public void run(){
BufferedWriter writer=null;
try{
// 从Socket当中得到OutputStream对象 ,发送数据给客户端
writer =new BufferedWriter(new OutputStreamWriter(socket.getOutputStream()));
writer.write("ServerSocket get!");
writer.flush(); //一定要的
} catch (IOException e) {
e.printStackTrace();
}
}
}
客户端:
主要代码:
1.在子线程中,Socket socket = new Socket("192.168.1.212", 1989);//创建一个Socket对象,传入服务器ip地址和端口号。
2.在子线程中,socket.getOutputStream() ;或socket.getInputStream() ;//获取输入流来读取服务器内容和获取输出流来发送数据给服务器。如果用到缓冲,记得flush();
3.关流时:socket.shutdownOutput() ;或socket.shutdownInput();
一般输入和输出都单独开个子线程。
package com.liuzhcheng.socketdemo;
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.text.TextUtils;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
public class MainActivity extends Activity {
Button send;
EditText editText;
TextView text;
Handler handler;
Socket socket;
String str;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
editText=(EditText) findViewById(R.id.edit_data);
text=(TextView) findViewById(R.id.server_text);
handler=new Handler(){
@Override
public void handleMessage(Message msg) {
if(msg.what==0x11){
text.setText((String)msg.obj);
}
}
};
send=(Button) findViewById(R.id.button_send);
send.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
str=editText.getText().toString();
if(!TextUtils.isEmpty(str)) {
new Thread() {
public void run(){
try {
//连接服务器,ip地址和端口号
// socket=new Socket();
// socket.connect(new InetSocketAddress("192.168.1.212", 1989), 5000);
socket = new Socket("192.168.1.212", 1989);
} catch (Exception e) {
e.printStackTrace();
}
if (socket != null) {
new MyThread(str, socket).start();
new MyThread2(handler,socket).start();
}
}
}.start();
}
}
});
}
}
class MyThread extends Thread {
String send_data;
Socket socket=null;
OutputStream out=null;
public MyThread(String str,Socket socket) {
send_data = str;
this.socket=socket;
}
@Override
public void run() {
try {
//获取输出流
out= socket.getOutputStream();
//向服务器发送信息
out.write(send_data.getBytes("gbk"));
out.flush();
socket.shutdownOutput();//关流
}catch (Exception e) {
e.printStackTrace();
}
}
}
class MyThread2 extends Thread {
Handler handler;
Socket socket=null;
InputStream in;
public MyThread2(Handler handler,Socket socket) {
this.handler=handler;
this.socket=socket;
}
@Override
public void run() {
//定义消息
Message msg = new Message();
msg.what = 0x11;
try {
in=socket.getInputStream();
int len;
byte[] buf=new byte[1024];
String str=null;
while((len=in.read(buf))!=-1){
str=new String(buf,0,len);
}
msg.obj=str;
handler.sendMessage(msg);
if(socket!=null){
socket.shutdownInput();//关流
}
}catch (Exception e) {
e.printStackTrace();
}
}
}