0
点赞
收藏
分享

微信扫一扫

Android socket通信 TCP协议


一、基于TCP协议的网络通信


TCP协议基础

IP协议即是Internet协议,使Internet成为一个允许连接不同类型的计算机和不同操作系统的网络。

TCP协议,建立一个连接,用于发送和接受数据的虚拟链路。

下图显示了TCP协议控制两个通信实体互相通信的示意图:

Android socket通信 TCP协议_通信


socket通常也称作"套接字",用于描述IP地址和端口,是一个通信链的句柄。在Internet上的主机一般运行了多个服务软件,同时提供几种服务。每种服务都打开一个Socket,并绑定到一个端口上,不同的端口对应于不同的服务

       网络上的两个程序通过一个双向的通讯连接实现数据的交换,这个双向链路的一端称为一个Socket。Socket通常用来实现客户方和服务方的连接。Socket是TCP/IP协议的一个十分流行的编程界面,一个Socket由一个IP地址和一个端口号唯一确定。

       在java中,Socket和ServerSocket类库位于java .net包中。ServerSocket用于服务器端,Socket是建立网络连接时使用的。在连接成功时,应用程序两端都会产生一个Socket实例,操作这个实例,完成所需的会话。

 这里可以参考疯狂android讲义的第13章内容。


二、下面实现一个简单的socket通信:

java程序,运行java类即可。弄一个简单的服务器:

import java.io.*;
import java.net.*;

public class SimpleServer {
public static void main(String[] args) throws IOException {

// 创建一个ServerSocket,用于监听客户端socket的连接请求
ServerSocket server = new ServerSocket(30001);

// 采用循环方式不断接受来自客户端的请求
while (true) {
// 每当接受到客户端Socket的请求,服务器端也对应产生一个Socket
Socket s = server.accept();
//获取输出流
writer.flush();
writer.close();*/

//通过输出流 向socket中写数据
OutputStream os=s.getOutputStream();
os.write("你好,我是服务器".getBytes("utf-8"));
os.close();
s.close();
}
}
}

再用建立一个android应用,使用socket与制定端口连接,获取数据等。

simpleClient.java

package com.example.simplecilent;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;

import android.os.Bundle;
import android.app.Activity;
import android.view.Menu;
import android.widget.EditText;

public class SimpleClient extends Activity {

EditText show;
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
show =(EditText)findViewById(R.id.show);
//关闭输入流、socket
try
{
Socket socket = new Socket("10.0.2.2" ,30001);
//将Socket对应的输入流包装成BufferedReader
//将服务器中传过来的数据 通过Inputstream读出来
BufferedReader br = new BufferedReader(
new InputStreamReader(socket.getInputStream()));
//进行普通IO操作
String line = br.readLine();
show.setText("收到了服务器的数据,内容是:" + line);
br.close();
socket.close();
}
catch (IOException e)
{
e.printStackTrace();
}
}
}

layout的xml文件

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >

<EditText
android:id="@+id/show"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:cursorVisible="false"
android:editable="false" >
</EditText>

</LinearLayout>

实现的效果图:


Android socket通信 TCP协议_通信_02


这里简单的概述一下socket通信大家遇到的几个问题:



1.很多同学,按照疯狂java讲义上面的实现,发现都可以,就是接受不到数据,这里

如果你用的AVD,地址端口应该改为10.0.2.2,就可以正常通信了。

2.很多同学,用的android版本比较高,运行说“Unfortunately,XXX has stopped”,

其实高版本是不支持socket通信的,需要多线程实现,但是这里好像还不是吧,我可以把这个删除:


<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="18" />

试试?



3这个大家都知道:加permission

<uses-permission android:name="android.permission.INTERNET" />

三、多线程

具体也不介绍了,大家看书。

建立一个android应用,ThreadClient


Android socket通信 TCP协议_通信_03

CilentThread.java

package com.example.multithreadclient;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;
import android.os.Handler;
import android.os.Message;

public class ClientThread implements Runnable
{
// 该线程负责处理的Socket
private Socket s;
private Handler handler;
// 该线程所处理的Socket所对应的输入流 收到的数据
BufferedReader br = null;

public ClientThread(Socket s, Handler handler) throws IOException
{
this.s = s;
this.handler = handler;
br = new BufferedReader(new InputStreamReader(s.getInputStream()));
}

public void run() {
try {
String content = null;
// 不断读取Socket输入流中的内容。
while ((content = br.readLine()) != null) {
// 每当读到来自服务器的数据之后,发送消息通知程序界面显示该数据
Message msg = new Message();
msg.what = 0x123;
msg.obj = content;
handler.sendMessage(msg);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}

MainActivity.java


package com.example.multithreadclient;

import java.io.OutputStream;
import java.net.Socket;
import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;

public class MainActivity extends Activity {

// 定义界面上的两个文本框
EditText input, show;
// 定义界面上的一个按钮
Button send;

OutputStream os;
Handler handler;

@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
input = (EditText) findViewById(R.id.input);
send = (Button) findViewById(R.id.send);
show = (EditText) findViewById(R.id.show);
Socket s;

handler = new Handler() {
@Override
public void handleMessage(Message msg)
{
// 如果消息来自于子线程
if (msg.what == 0x123)
{
// 将读取的内容追加显示在文本框中
show.append("\n" + msg.obj.toString());
}
}
};

try
{
s = new Socket("10.0.2.2", 30006);
// 客户端启动ClientThread线程不断读取来自服务器的数据
new Thread(new ClientThread(s, handler)).start(); // ①
os = s.getOutputStream();
} catch (Exception e) {
e.printStackTrace();
}

send.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
try
{
// 将用户在文本框内输入的内容写入网络
os.write((input.getText().toString()+"\r\n")
.getBytes("utf-8"));
// 清空input文本框
input.setText("");
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
}


布局文件 xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >

<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="horizontal" >

<!-- 定义一个文本框,它用于接受用户的输入 -->

<EditText
android:id="@+id/input"
android:layout_width="240px"
android:layout_height="wrap_content" />

<Button
android:id="@+id/send"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:paddingLeft="8px"
android:text="send" />
</LinearLayout>
<!-- 定义一个文本框,它用于显示来自服务器的信息 -->

<EditText
android:id="@+id/show"
android:layout_width="fill_parent"
android:layout_height="67dp"
android:cursorVisible="false"
android:editable="false"
android:gravity="top" />

</LinearLayout>


java类 建立一个服务器


Android socket通信 TCP协议_通信_04

MySerer.java

import java.net.*;
import java.io.*;
import java.util.*;

public class MyServer {

// 定义保存所有Socket的ArrayList
public static ArrayList<Socket> socketList = new ArrayList<Socket>();

public static void main(String[] args) throws IOException
{
ServerSocket ss = new ServerSocket(30006);
while (true)
{
// 此行代码会阻塞,将一直等待别人的连接
Socket s = ss.accept();
socketList.add(s);
// 每当客户端连接后启动一条ServerThread线程为该客户端服务 将socket s传过去
new Thread(new ServerThread(s)).start();
}
}
}


ServerThread.java

import java.io.*;
import java.net.*;
import java.util.*;

//负责处理每个线程通信的线程类
public class ServerThread implements Runnable {

// 定义当前线程所处理的Socket
Socket s = null;
// 该线程所处理的Socket所对应的输入流
BufferedReader br = null;

//socket s调用
public ServerThread(Socket s) throws IOException
{
this.s = s;
// 初始化该Socket对应的输入流 将传过来的socket中的数据读出来
br = new BufferedReader(new InputStreamReader(s.getInputStream(),
"utf-8")); // ②
}

public void run() {
try {
String content = null;
// 采用循环不断从Socket中读取客户端发送过来的数据
while ((content = readFromClient()) != null) {
// 遍历socketList中的每个Socket,
// 将读到的内容向每个Socket发送一次
for (Socket s : MyServer.socketList) {
OutputStream os = s.getOutputStream();
os.write((content + "\n").getBytes("utf-8"));
}
}
} catch (IOException e) {
e.printStackTrace();
}
}

// 定义读取客户端数据的方法
private String readFromClient() {
try
{
return br.readLine();
}
// 如果捕捉到异常,表明该Socket对应的客户端已经关闭
catch (IOException e) {
// 删除该Socket。
MyServer.socketList.remove(s); // ①
}
return null;
}
}


具体效果图


Android socket通信 TCP协议_java_05

文章具体参考:《疯狂android讲义》,问题上面已经说过。

好了,小菜鸟初学android,还请指教。

举报

相关推荐

0 条评论