一、思路:
1、首先需要一个服务器,一个客户端:
PC作为服务器,手机Android作为客户端
2、服务器:接收流后将流输出并加上标识后再以流输出发送给客户端
3、客户端:将编辑框输入的字符串以字节流输出给服务器,再接收服务器的流并显示到另一个编辑框内!
4、大体思路如此!其他细节:
A:虽然setText()中括号里是int型数据,但任然可以在里面写字符串,因为EditText继承了TextView
B:流结束要有标识符
C:组件通过查找对应的ID并转型:
button_sendContent = (Button) this.findViewById(R.id.button_sendContent);//发送按钮
edit_content = (EditText) this.findViewById(R.id.edit_content);// 发送内容的编辑框
D:页面的跳转:
// 用户名个密码都正确后则跳转页面
Intent intent = new Intent(FirstActivity.this,
SecondActivity.class);
FirstActivity.this.startActivity(intent);
E:之后添加的Activity需要注册:
<activity android:name=".SecondActivity"></activity>
F:使用互联网,需要添加互联网权限:
二、源代码及其注释:
1、服务器PC端:
package androidke.flycatdeng.lesson002;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
/**
* 服务器PC
* @author flycatdeng
*
*/
public class ChatServer {
// 声明
Socket client;// 客户机对象
OutputStream ous;// 输出流对象
InputStream ins;// 输入流对象
/**
* 启动服务器方法
*/
public void processChat(int port) throws Exception {
ServerSocket server = new ServerSocket(port);// 首先创建一个服务器并指定窗口
System.out.println("服务器创建成功,端口:" + port);//打印端口
// 服务器处于阻塞等待状态,但是如果这样就像手机接电话一样 只能一个客户,所以我们要等待循环
while (true) {
client = server.accept();
System.out.println("有客户进来哒,IP是:" + client.getRemoteSocketAddress());// 打印客户的IP地址
dealClient(client);// 处理客户
}
}
// 处理用户的方法
public void dealClient(Socket client) throws Exception {
// 从连结对象上得到输入输出流对象
ous = client.getOutputStream();// 这个输出的数据将会给连结对象(客户)
ins = client.getInputStream();// 这个是客户机上输入的流
String s = "Hello,welcome to use CC\r\n";// 欢迎词
sendMSg(s);// 发送欢迎语
String inputs = readString(ins);//读取从客户机传来的流并转换为字符串
while (!inputs.equals("bye")) {//如果读取到的不是bye则继续读
System.out.println("读到的客户机说:" + inputs);
String s2 = "client send:" + inputs + "\r\n";
System.out.println("正准备给客户机发送:" + s2);
sendMSg(s2);//将流发送给客户机
inputs = readString(ins);//继续读客户机传来的流
}
// 如果输入的字节是bye
s = "welcome to here next time \r\n";
sendMSg(s);
client.close();//关闭与客户的连结
}
/**
* 将要输出的字符串封装在一个方法里,以便调用
* @param s :得到的一个从客户机输入的字符串
*/
public void sendMSg(String s) throws IOException {
System.out.println("发送了" + s);
ous.write(s.getBytes());//将字符串以字节数组读出
ous.flush();//强制完全输出
}
/**
* 读取输入流(一个一个字节的读),并返回输入的字符串
* @param ins:输入流
* @return:返回输入的字符串
* @throws Exception
*/
public String readString(InputStream ins) throws Exception {
System.out.println("开始读流了!!");
// 创建一个字符串缓冲区
StringBuffer stb = new StringBuffer();
int in = ins.read();
System.out.println("这里执行了吗?");
char c;
while (in != 13) {// 当不是回车键的时候
c = (char) in;// 强制将int型in转换为char类型
stb.append(c);// 将字符一个一个的附加
in = ins.read();// 再读
}
String inputS = stb.toString().trim();// 将stb转换成字符串并去掉末尾的空格
System.out.println("读完流了!!");
return inputS;
}
// 主函数
public static void main(String[] args) {
ChatServer cs = new ChatServer();
try {
cs.processChat(8090);
} catch (Exception e) {
e.printStackTrace();
}
}
}
2、客户端Android:
第一个Activity:FirstActivity:
package androidke.flycatdeng.lesson002;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.net.UnknownHostException;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
public class FirstActivity extends Activity {
// 声明
Button button_send;
EditText edit_username, edit_password;
Socket client;
static InputStream ins;// 静态输入流对象
static OutputStream ous;// 静态输出流对象
// 这个Activity重写的onCreate方法相当于主函数
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
try {
client = new Socket("220.168.117.31", 8090);//在显示页面之前创建客户对象
System.out.println("已经创建客户");
ous = client.getOutputStream();
ins = client.getInputStream();
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
setContentView(R.layout.main);// 主页面为main.xml
// 可视后取得各个组件的id并强制转换为相应的组件类型
button_send = (Button) this.findViewById(R.id.button_send);// 提交按钮
edit_username = (EditText) this.findViewById(R.id.edit_username);// 用户名编辑框
edit_password = (EditText) this.findViewById(R.id.edit_password);// 密码编辑框
// 给按钮添加(设置)监听器
button_send.setOnClickListener(ocl);
}
// 内部匿名类
OnClickListener ocl = new OnClickListener() {// 这个包引进的时候需要注意,选择的是第二个:android.view.View.OnClickListener;
// 重写方法
public void onClick(View v) {
// 将编辑框的内容得到并转换为字符串
String username = edit_username.getText().toString();
String password = edit_password.getText().toString();
if ("d".equals(username) && "1".equals(password)) {
// 用户名个密码都正确后则跳转页面
Intent intent = new Intent(FirstActivity.this,
SecondActivity.class);
FirstActivity.this.startActivity(intent);
} else {
// 如果登录错误则提示
Toast.makeText(FirstActivity.this, "用户名不存在活密码错误!", 3).show();// 副本,内容,停留时间以秒为单位
}
}
};
}
第二个Activity:SecondActivity:
package androidke.flycatdeng.lesson002;
import java.io.InputStream;
import java.net.Socket;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
public class SecondActivity extends Activity{
// 声明
Button button_sendContent;
EditText edit_content;
TextView TextView_show;
String content;
Socket client;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.second);// 转到第二个页面second.xml
// //跳转页面后取得其服务器ip和端口
// serverIP=this.getIntent().getStringExtra("localhost");
// port=this.getIntent().getIntExtra("8090", 8090);
//创建客户端 对象
System.out.println("执行到这里!!!!!!!!!!");
try {
processChat();//显示服务器发来的消息的方法
} catch (Exception e) {
e.printStackTrace();
}
button_sendContent = (Button) this.findViewById(R.id.button_sendContent);//发送按钮
edit_content = (EditText) this.findViewById(R.id.edit_content);// 发送内容的编辑框
button_sendContent.setOnClickListener(ocl);
}
// 内部匿名类
OnClickListener ocl = new OnClickListener() {// 这个包引进的时候需要注意,选择的是第二个:android.view.View.OnClickListener;
// 重写方法
public void onClick(View v) {
content=edit_content.getText().toString();
System.out.println("客户端文本框输入的内容是:"+content);
try {
sendMSg(content+"\r\n");//将得到的编辑框内的内容以流输出
edit_content.setText("");//将其内容设置为空
content=edit_content.getText().toString();//再显示
processChat();//显示服务器发来的消息的方法,鼠标每次点击按钮都调用这个显示的方法
} catch (Exception e) {
e.printStackTrace();
}
}
};
//创建客户的方法
public void processChat() throws Exception{
System.out.println("执行到这里了!!!!!!!!!!!!!");
String inputs=readString(FirstActivity.ins);//得到了服务器传来的字符串
System.out.println(inputs);//打印是否得到了服务器传来的字符串
TextView_show = (TextView) this.findViewById(R.id.TextView_show);// 显示内容的编辑框
TextView_show.setText(inputs);//设置上面的文本为得到的流的转换的字符串
TextView_show.getText().toString();//将其转换为字符串,如果没有这一句,文本将不会显示
}
/**
* 将要输出的字符串封装在一个方法里,以便调用
* @param s :得到的一个从客户机输入的字符串
*/
public void sendMSg(String s) throws Exception{
System.out.println("在发送吗?");
FirstActivity.ous.write(s.getBytes());
FirstActivity.ous.flush();
System.out.println("向服务器发送流完成");
}
/**
* 读取输入流(一个一个字节的读),并返回输入的字符串
* @param ins:输入流
* @return:返回输入的字符串
* @throws Exception
*/
public String readString(InputStream ins) throws Exception {
//创建一个字符串缓冲区
StringBuffer stb=new StringBuffer();
int in=ins.read();
char c;
while (in != 13) {// 当不是回车键的时候
c = (char) in;// 强制将int型in转换为char类型
stb.append(c);// 将字符一个一个的附加
in = ins.read();// 再读
}
String inputS=stb.toString().trim();//将stb转换成字符串并去掉末尾的空格
return inputS;
}
}
3、第一个页面:main.xml:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent" > <!-- 这下面的前两句是每个组件必要的属性 --> <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="欢迎使用手机CC" /> <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="用户名:" /> <EditText android:layout_width="fill_parent" android:layout_height="wrap_content" android:id="@+id/edit_username" /> <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="密码:" /> <EditText android:layout_width="fill_parent" android:layout_height="wrap_content" android:id="@+id/edit_password" /> <Button android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="提交" android:id="@+id/button_send" /> </LinearLayout>
4、第二个页面:second.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="登录成功"
/>
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:id="@+id/TextView_show"
/>
<EditText
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:singleLine="false"
android:id="@+id/edit_content"
/>
<Button
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="发送"
android:id="@+id/button_sendContent"
/>
</LinearLayout>
5、效果: