足迹二:Android客户端与PC服务端之间的SOCKET通讯实现登陆功能(客户端 仅供学习)

http://my.eoe.cn/android_zyz/archive/3394.html


第一步:编写实体类User、FCMessage、Sex,参考足迹一里面的实体类
第二步:编写登陆界面(参考QQ)login.xml

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@drawable/login_bg"
    android:orientation="vertical" >
    <!-- 头像 -->
    <ImageButton
        android:id="@+id/login_head"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentTop="true"
        android:layout_centerHorizontal="true"
        android:layout_marginTop="50dp"
        android:background="#00000000"
        android:src="@drawable/login_default_avatar" />
    <!-- 账号 -->
    <AutoCompleteTextView
        android:id="@+id/login_account"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_below="@id/login_head"
        android:layout_centerHorizontal="true"
        android:layout_marginBottom="-4dp"
        android:layout_marginLeft="30dp"
        android:layout_marginRight="30dp"
        android:layout_marginTop="10dp" />
    <!-- 密码 -->
    <EditText
        android:id="@+id/login_pwd"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_below="@id/login_account"
        android:layout_centerHorizontal="true"
        android:layout_marginLeft="30dp"
        android:layout_marginRight="30dp"
        android:layout_marginTop="-4dp"
        android:hint="@string/login_pwd_hint"
        android:inputType="textPassword" />
    <!-- 登陆按钮 -->
    <Button
        android:id="@+id/login_btn_logining"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_below="@id/login_pwd"
        android:layout_centerHorizontal="true"
        android:layout_marginLeft="30dp"
        android:layout_marginRight="30dp"
        android:background="@drawable/login_button_nor"
        android:text="@string/btn_login" />
    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_below="@id/login_btn_logining"
        android:layout_centerHorizontal="true"
        android:layout_marginLeft="30dp"
        android:layout_marginRight="30dp"
        android:layout_marginTop="5dp" >
        <!-- 取回密码 -->
        <Button
            android:id="@+id/login_btn_getbackpwd"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentLeft="true"
            android:layout_marginLeft="20dp"
            android:background="#00000000"
            android:text="@string/get_pwd"
            android:textColor="#ffffff"
            android:textSize="15sp" />
        <!-- 登录设置 -->
        <Button
            android:id="@+id/login_btn_setlogin"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentRight="true"
            android:layout_marginRight="20dp"
            android:background="#00000000"
            android:text="@string/set_login"
            android:textColor="#ffffff"
            android:textSize="15sp" />
    </RelativeLayout>
    <!-- 跳转注册界面 -->
    <Button
        android:id="@+id/login_btn_to_register"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:layout_centerHorizontal="true"
        android:layout_marginLeft="30dp"
        android:layout_marginRight="30dp"
        android:background="@drawable/login_btn_register"
        android:text="@string/btn_register" />
</RelativeLayout>

效果图:
足迹二登陆界面.png
第三步:编写java代码类LoginActivity

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
package com.durian.fc;

import java.util.ArrayList;
import java.util.List;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.ArrayAdapter;
import android.widget.AutoCompleteTextView;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageButton;
import android.widget.Toast;
import com.durian.fc.entity.User;
import com.durian.fc.service.FCClient;

public class LoginActivity extends Activity {
    // 用户的头像
    private ImageButton userHead;
    // 用户的账号
    private AutoCompleteTextView userAccount;
    // 用户密码
    private EditText userPwd;
    // 登陆按钮、取回密码按钮、登录设置按钮、注册登录按钮
    private Button btnLogining, btnGetBackPwd, btnSetLogin, btnToRegister;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.login);
        //初始化界面控件
        initView();
        //添加监听响应事件
        addListener();
    }

    /**
     * 初始化所有控件
     */
    private void initView() {
        userHead = (ImageButton) findViewById(R.id.login_head);
        userAccount = (AutoCompleteTextView) findViewById(R.id.login_account);
        userPwd = (EditText) findViewById(R.id.login_pwd);
        btnLogining = (Button) findViewById(R.id.login_btn_logining);
        btnGetBackPwd = (Button) findViewById(R.id.login_btn_getbackpwd);
        btnSetLogin = (Button) findViewById(R.id.login_btn_setlogin);
        btnToRegister = (Button) findViewById(R.id.login_btn_to_register);
    }

    private void addListener() {
        //添加登陆按钮监听事件
        btnLogining.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                //获取用户输入的账号
                int account = Integer
                        .parseInt(userAccount.getText().toString());
                //获取用户输入的密码
                String password = userPwd.getText().toString();
                //调用登录方法
                login(account, password);
            }
        });

    }
    /**
     * 登录方法
     * 该方法用于将用户输入的账号和密码发送到服务端,并对服务端返回的数据进行处理
     * @param account 账号
     * @param password 密码
     */
    protected void login(int account, String password) {
        //创建一个用户,用于向服务端发送数据时,存放的实体
        User user = new User();
        user.setAccount(account);
        user.setPassword(password);
        user.setOperation("login");
        //调用服务方法,向服务端发送数据,如果服务端返回true表示登陆成功,false表示登录失败
        boolean b = new FCClient().sendLoginInfo(user);
        if (b) {//如果登陆成功
            try {
                // 发送一个要求返回在线好友的请求的message
                // --- <span style="white-space:pre"> </span>
            } catch (Exception e) {
                e.printStackTrace();
            }
            Intent intent = new Intent(this, TestActivity.class);
            //new一个Bundle对象,并将要传递的数据传入
            Bundle bundle = new Bundle();
            bundle.putInt("account", account);
            bundle.putString("password", password);
            //将bundle对象assign给Intent
            intent.putExtras(bundle);
            //开启跳转
            startActivity(intent);
        } else {//登录失败,通过Toast向用户提示登录失败
            Toast.makeText(this, "登录失败,不告诉你为什么...", Toast.LENGTH_LONG).show();
        }
    }
}

第四步:编写一个客户端的service业务类

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
package com.durian.fc.service;

import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OptionalDataException;
import java.io.Serializable;
import java.io.StreamCorruptedException;
import java.net.InetSocketAddress;
import java.net.Socket;
import android.util.Log;
import com.durian.fc.entity.FCMessage;

public class FCClient implements Serializable{
    public Socket s;
    /**
     * 向服务器发送数据
     */
    public boolean sendLoginInfo(Object obj){
        boolean b = false;
        try {
            try {
                //设置服务端的dstName和dstPost
                s = new Socket("192.168.1.101", 9999);
            } catch (IOException e) {
                e.printStackTrace();
                //连接服务器超时
                return false;
            }
            //输出发送
            ObjectOutputStream oos = new ObjectOutputStream(s.getOutputStream());
            oos.writeObject(obj);
            //接收服务端的响应
            ObjectInputStream ois = new ObjectInputStream(s.getInputStream());
            FCMessage msg = (FCMessage)ois.readObject();
            //如果服务端返回SUCCESS时
            if(FCMessage.SUCCESS.equals(msg.getType())){
                //创建一个该账号和服务器保持连接的线程
                //待定
                b = true;
            }else if(FCMessage.FAIL.equals(msg.getType())){
                b = false;
            }
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        return b;
    }
}

第五步:编写一个用于表示登陆成功的界面test.xml布局

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >
    <TextView 
        android:id="@+id/tv_test"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:text="欢迎"/>
</LinearLayout>

第六步:编写相应的java代码TestActivity

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
package com.durian.fc;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.widget.TextView;

public class TestActivity extends Activity {
    private TextView tvTest;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        // TODO Auto-generated method stub
        super.onCreate(savedInstanceState);
        setContentView(R.layout.test);
        //初始化界面
        initView();
        //初始化数据
        initData();
    }
    private void initData() {
        //获取从上一个界面传递过来的数据
        Bundle bundle = this.getIntent().getExtras();
        //定义一个字符串用于显示用户的信息账号
        String text = tvTest.getText().toString();
        text = text + bundle.getInt("account") + "登陆";
        //设置TextView显示的文本信息
        tvTest.setText(text);
    }
    private void initView() {
        //通过id获取组件的实例
        tvTest = (TextView)findViewById(R.id.tv_test);
    }
}

第七步:在AndroidManifest.xml定义新的Activity:TestActivity,并添加一个INTERNET的权限

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.durian.fc"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="10"
        android:targetSdkVersion="10" />
    <uses-permission android:name="android.permission.INTERNET"/>

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@android:style/Theme.NoTitleBar" >
        <activity
            android:name="com.durian.fc.LoginActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <activity android:name="MainActivity"/>
        <activity android:name="TestActivity"/>
    </application>
</manifest>

第八步:测试
服务端开启socket,运行LoginServerTest类
足迹二测试服务端开启.png
运行安装客户端到虚拟机
足迹二测试客户端1.png
登录失败时
足迹二测试客户端登录失败.png
登陆成功时
足迹二测试客户端登录成功.png
至此,客户端与服务端之间的socket就可以实现登录功能!!!


  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
3.1 控件基本方法(method) 3.1.1 S_InitListen 函数原型 :SHORT S_InitListen(SHORT m_Port) 功能 : 建立服务器端侦听端口 参数 : m_Port 服务器侦听端口号 返回值: :0:成功 1:失败 3.1.2 S_OnSendMsg 函数原型 :SHORT S_OnSendMsg(LPCTSTR m_ip, LPCTSTR m_Msg); 功能 : 单条消息发送 参数 : m_ip 接收端Ip地址 m_Msg 消息信息 返回值: :0 发送成功 1 发送失败 3.1.3 S_OnPushMsg 函数原型 :SHORT S_OnPushMsg(LPCTSTR m_Msg); 功能 : 群发消息 参数 : m_Msg 消息信息 返回值: :0 成功 1:失败 3.1.4 C_OnConnect 函数原型 :SHORT C_OnConnect(LPCTSTR m_ip, SHORT m_port); 功能客户端连接服务器 参数 : m_ip 服务器端ip地址 参数 : m_port 端口号 返回值: :0 成功 1失败 3.1.5 C_OnSendMsg 函数原型 :SHORT C_OnSendMsg(LPCTSTR m_Msg); 功能 : 发送消息 参数 : m_Msg 消息信息 返回值: :0 成功 1失败 3.2 控件事件(event) 3.2.1 FireReceiveSocketMsg 原型 :void FireReceivedSocketMsg(SHORT m_Event, LPCTSTR m_Msg) 功能客户端消息 参数 : m_Event 事件类型 1:客户端消息事件 2:客户端通讯错误事件 参数 : m_Msg 事件信息 3.2.2 FireServerReceiveSocketMsg 原型 :void FireServerReceivedSocketMsgWinsocketocxctrl(SHORT m_Event, LPCTSTR m_Msg , LPCTSTR m_Address) 功能 :服务器端消息 参数 : m_Event 事件类型 1:服务器端消息事件 2: 服务器通讯错误事件 3:客户端连接到服务器通知事件(返回客户端ip) 4:客户端断开服务器通知事件(返回客户端ip) 参数 : m_Msg 事件信息 参数 : m_ Address 客户端ip地址 .4 备注 通讯日志存储在C:\ _SOCKET.LOG
最新版Socket编程,后面带有程序实例,并通过调试,可以直接编译运行;希望对大家有帮助。代码设计服务端客户端socket实例,设计IPV4、IPV6的实例代码。 网络的Socket数据传输是一种特殊的I/O,Socket也是一种文件描述符。Socket也具有一个类似于打开文件的函数调用Socket(),该函数返回一个整型的Socket描述符,随后的连接建立、数据传输等操作都是通过该Socket实现的。 部分代码(服务器): #include #include #include #include #include #include #include #include #define SERVPORT 3333 /*服务器监听端口号 */ #define BACKLOG 10 /* 最大同时连接请求数 */ main() { int sockfd,client_fd; /*sockfd:监听socket;client_fd:数据传输socket */ struct sockaddr_in my_addr; /* 本机地址信息 */ struct sockaddr_in remote_addr; /* 客户端地址信息 */ if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) { perror( "socket创建出错!"); exit(1); } my_addr.sin_family=AF_INET; my_addr.sin_port=htons(SERVPORT); my_addr.sin_addr.s_addr = INADDR_ANY; bzero( &(my_addr.sin_zero),8); if (bind(sockfd, (struct sockaddr *) &my;_addr, sizeof(struct sockaddr)) == -1) { perror( "bind出错!"); exit(1); } if (listen(sockfd, BACKLOG) == -1) { perror( "listen出错!"); exit(1); } while(1) { sin_size = sizeof(struct sockaddr_in); if ((client_fd = accept(sockfd, (struct sockaddr *) &remote;_addr, &sin;_size)) == -1) { perror( "accept出错"); continue; } printf( "received a connection from %s\n", inet_ntoa(remote_addr.sin_addr)); if (!fork()) { /* 子进程代码段 */ if (send(client_fd, "Hello, you are connected!\n", 26, 0) == -1) perror( "send出错!"); close(client_fd); exit(0); } close(client_fd); } } }

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值