Android中使用Socket与服务器通信,服务器报Connection reset的错


鄙人初次使用Android进行邮件服务系统客户端的开发,想利用socket与小伙伴编写的服务器进行通信,实现登陆注册功能。所使用的协议是自己自定义的(不过这不是重点)。但登录时总会卡在new Socket(IP,port)上,该语句一执行完,服务器就会报Connection Reset的错。

图片描述

经过网上搜集资料,原因可能是客户端建立了套接字,但服务器从输入输出流中读取数据之前,客户端socket就已经关闭了。
但是在Android中进行Debug发现,报错就在执行完
client = new Socket(ServerInfo.sockethost, ServerInfo.socketport);
后出现。


上代码。

客户端:


 public class Login extends Activity {

    private Intent intent = null;
    private EditText account = null; // 账号
    private EditText passwpord = null; // 密码
    private Button login = null; // 登录
    private TextView register = null; // 注册

    private String useraccount = null;
    private String userpassword = null;

    private Dialog m_Dialog = null; // 提示
    private Handler m_Handler = null; // 指向某一个线程的句柄

    private Socket client; // 客户端套接字
    private BufferedReader reader;
    private PrintWriter writer;

    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_login);

        intent = this.getIntent();

        account = (EditText) this.findViewById(R.id.login_account);
        passwpord = (EditText) this.findViewById(R.id.login_password);
        login = (Button) this.findViewById(R.id.login_button);
        register = (TextView) this.findViewById(R.id.login_register);

        register.setClickable(true); // 设置可作为按键触摸
        // 设置登录按键事件
        login.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                useraccount = account.getText().toString();
                userpassword = account.getText().toString();

                // 判断账号填写是否为空
                if (Regex.isEmpty(useraccount)) {
                    Toast.makeText(getApplicationContext(), "请填写用户账号!",
                            Toast.LENGTH_SHORT).show();
                }
                // 判断账号是否符合邮件格式
                else if (Regex.isEmail(useraccount)) {
                    Toast.makeText(getApplicationContext(), "用户账号格式不正确!",
                            Toast.LENGTH_SHORT).show();
                }
                // 判断密码是否为空
                else if (Regex.isEmpty(userpassword)) {
                    Toast.makeText(getApplicationContext(), "请填写密码!",
                            Toast.LENGTH_SHORT).show();
                } else {
                    System.out.println("Client:Connecting");
                    m_Dialog = ProgressDialog.show(Login.this, "提示", "登录中...",true);

                    // 创建一个新的线程
                    new Thread(new Runnable() {
                        int flag = 0;           // 标志位,0表示登录成功,1表示登录失败
                        int mark = 0;

                        // 登录一系列操作,基于自定义的EMSP协议
                        @Override
                        public void run() {
                            try {
                                // 创建一个Socket对象,并指定服务端的IP及端口号
                                System.out.println("new Socket('', 6666);");
                                // 创建一个Socket对象,并指定服务端的IP及端口号
                                client = new Socket(ServerInfo.sockethost,  ServerInfo.socketport);
                                System.out.println("Socket 'client' created.");

                                String command = null;
                                System.out.println("new reader.");
                                // 输入输出流读写器
                                reader = new BufferedReader(
                                        new InputStreamReader(client.getInputStream()));
                                System.out.println("new writer.");
                                writer = new PrintWriter(client.getOutputStream(), true);
                                // 登录第一步,向服务器发送登录请求,C:login
                                writer.println("login");

                                while ((command = reader.readLine()) != null) {
                                    System.out.println("++++mark = " + mark);
                                    System.out.println("我在while里");

                                    StringTokenizer stk = new StringTokenizer(command);
                                    String cmd = stk.nextToken();
                                    System.out.println("cmd:" + cmd);
                                    if (cmd.equals("user")) {
                                        writer.println(useraccount);
                                        System.out
                                                .println("writer.println('useraccount');");
                                    } else if (cmd.equals("pass")) {
                                        writer.println(userpassword);
                                        System.out
                                                .println("writer.println('userpassword');");
                                    } else if (cmd.equals("inexist")) {
                                        writer.println(useraccount);
                                        System.out
                                                .println("inexist,  writer.println('username');");
                                    } else if (cmd.equals("error")) {
                                        writer.println(useraccount);
                                        System.out
                                                .println("error,  writer.println('username');");
                                    } else if (cmd.equals("loginok")) {
                                        System.out.println("case 'loginok'");
                                        mark = 1;
                                        System.out.println("========mark = "
                                                + mark);
                                        break;
                                    }
                                }
                                System.out.println("至此,登录成功,flag=0");

                                // 至此,登录成功,flag=0
                            } catch (Exception e) {
                                flag = 1; // 登录失败
                                e.printStackTrace();
                            } finally {
                                try {
                                    if (client != null)
                                        client.close();
                                } catch (IOException e) {
                                    e.printStackTrace();
                                }
                            }
                            // 开辟一个新线程反馈登录是否成功
                            m_Handler.post(new Runnable() {
                                @Override
                                public void run() {
                                    if (flag == 0) {
                                        // 全局变量记录用户名和密码
                                        ServerInfo.username = useraccount;
                                        ServerInfo.password = userpassword;
                                        // 跳转到主界面列表
                                        intent.setClass(Login.this,
                                                MainActivity.class);
                                        Bundle bundle = new Bundle();
                                        bundle.putString("username",
                                                useraccount);
                                        bundle.putString("password",
                                                userpassword);
                                        intent.putExtras(bundle);
                                        startActivity(intent);
                                        Login.this.finish();
                                        System.out
                                                .println("Client: Login succeed!");
                                        Toast.makeText(getApplicationContext(),
                                                "登录成功!", Toast.LENGTH_SHORT)
                                                .show();
                                    } else {
                                        Toast.makeText(getApplicationContext(),
                                                "登录失败!", Toast.LENGTH_SHORT)
                                                .show();
                                    }
                                }
                            });
                            m_Dialog.dismiss(); // 从屏幕上消除Dialog
                        }
                    }).start();
                }
            }
        });

        // 设置触摸“注册新用户”后响应事件
        register.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View arg0) {
                intent.setClass(Login.this, Register.class);
                startActivity(intent);
                Login.this.finish();
            }
        });
    }
}

服务器端(只粘贴部分关键代码):


 public class tempEMSP implements Runnable {
    private Socket socket;
    private ZenMailServerService dbm;

    private BufferedReader bffreader = null;
    private PrintStream print = null;
    private String username;

    public tempEMSP(Socket socket, ZenMailServerService dbm) throws IOException {
        this.socket = socket;
        this.dbm = dbm;
        bffreader = new BufferedReader(new InputStreamReader(
                socket.getInputStream()));
        print = new PrintStream(socket.getOutputStream());
    }

    @Override
    public void run() {
        // TODO Auto-generated method stub
        print.println("emsp Service is OK");
        String command;

        boolean auth = false;
        String stat = null;
        stat = "login";
        boolean login = false;
        try {
            while ((command = bffreader.readLine()) != null) {
                StringTokenizer stk = new StringTokenizer(command);
                switch (stk.nextToken()) {
                case "login":
                    System.out.println("==========EMSP Server To Client : login");
                    loginRespon();
                    break;
                case "register":
                    registerRespon();
                    break;
                case "modify":
                    modifyRespon();
                    break;
                case "outbox":
                    outboxRespon();
                    break;
                case "inbox":
                    inboxRespon();
                    break;
                case "contact":
                    contactRespon();
                    break;
                case "black":
                    blackRespon();
                    break;
                case "quit":
                    quitRespon();
                    break;
                default:
                    break;
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

private void loginRespon() throws IOException {
        System.out.println("==========EMSP Server To Client : loginRespon()");
        print.println("user");
        System.out.println("==========EMSP Server To Client : print.println('user');"); 
        String command;
        while ((command = bffreader.readLine()) != null) {
            System.out.println("==========EMSP Server To Client : command="+ command);  
            StringTokenizer stk = new StringTokenizer(command);
            String cmd = stk.nextToken();
            System.out.println("==========EMSP Server To Client : cmd="+ cmd);  
            if (cmd.equals("quit"))
                return;
            if (this.dbm.isExistUser(cmd)) {
                username = cmd;
                System.out.println("this.dbm.isExistUser(cmd), username="+username);
                print.println("pass");
                System.out.println("EMSP Server:print.println('pass');");
                StringTokenizer stk1 = new StringTokenizer(bffreader.readLine());
                String pass = stk1.nextToken();
                System.out.println("EMSP Server: String pass =" + pass);
                if (this.dbm.getPassword(cmd).equals(pass)) {
                    System.out.println("print.println('loginok');");
                    print.println("loginok");
//                  bffreader.close();//2015.6.11
//                  print.close();
                    return;
                } else {
                    print.println("user"); // 重头输入用户名
                }
            } else {
                print.println("inexist");
            }
        }
    }

}


之前去请教过一些同学,有一个同学指出是因为Android编码的问题,不知道大虾们火眼金睛有何见解?这个问题困扰我整整一个星期了 (:з」∠)

Android socket connection-reset

潜水型图拉扬 10 years, 3 months ago

前不久在做android app开发的时候,也遇到过这个问题,在activity中创建new socket的时候,总是报connection reset by server,卡在这里很久,找不到原因,后来换了个思路,使用nio实现就没有这个问题了。

Ali92 answered 10 years, 3 months ago

不会是没添加网络权限吧...

飞奔的茶几 answered 10 years, 3 months ago

Your Answer