通信环境:
客户端:android手机 模拟器。采用sdk 6 , myEclipse8.5
服务端:pc电脑,采用控制台应用程序 , myEclipse9.1
socket通信是一种通讯协议,适用于c/s结构的应用程序,与编写的android应用程序刚好符合,今天编写一下android与pc机之间借助与socket协议来通讯的应用程序,目的是为了温习java.net包下一些类的使用方法。
此程序我在模拟器与真机上均测试成功,请注意,在使用真机测试时,需要有网络接入点,并且服务端需要和客户端在同一网段,假如电脑与手机都接入同一路由器共享上网,则可以实现通信。
服务端:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketException;
import java.util.Enumeration;
public class Server {
//监听器对象
private ServerSocket server;
/**
* 实例化,指定监端口
* @param port
*/
public Server(int port)
{
try {
//指定监听端口和最大访问数量
server = new ServerSocket(port, 10);
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 获取本机ip地址
*/
public String getLocalAddress(){
try {
//获取所有可用网络接口
Enumeration<NetworkInterface> networkInterfaces = NetworkInterface.getNetworkInterfaces();
while (networkInterfaces.hasMoreElements()) {
NetworkInterface networkInterface = (NetworkInterface)networkInterfaces.nextElement();
//获取接口内可用的地址信息
Enumeration<InetAddress> inetAddresses = networkInterface.getInetAddresses();
while (inetAddresses.hasMoreElements()) {
InetAddress inetAddress = (InetAddress) inetAddresses.nextElement();
//判断不为本地回环地址 , 及不为127.0.0.1
if(!inetAddress.isLoopbackAddress())
{
System.out.println(inetAddress.getHostName());
System.out.println(inetAddress.getHostAddress());
return inetAddress.getHostAddress();
}
}
}
} catch (SocketException e) {
e.printStackTrace();
}
//如果找不到地址,就用回环地址
return "127.0.0.1";
}
public void Listener()
{
while(true)
{
try {
System.out.println("开始监听 ----- 等待数据");
//开始监听,等待数据的到来
final Socket socket = server.accept();
//新的线程
new Thread( new Runnable() {
public void run() {
//缓冲器
BufferedReader in;
try {
in = new BufferedReader(new InputStreamReader(socket.getInputStream() , "UTF-8"));
while(!socket.isClosed()){
String str;
str = in.readLine();
if(str == null)
break;
System.out.println(str);
}
System.out.println("--------------------");
socket.close();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}).start();
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
* 入口
* @param args
*/
public static void main(String[] args) {
//设置9758为服务器监听端口
new Server(9758).Listener();
}
}
其中有一个方法getLocalAddress() ,是为了获取本地网卡ip地址,在.net 中如果要使用监听则需要获取本地ip地址,java中则不用,所以此方法暂时得不到使用
值得注意的是,代码中以9758为监听端口,0-1024为系统端口,一般自定义端口不要在此范围内,一般的端口定义可以在1025 - 60000(多) , 在此范围内可以自己选择,
但是要注意,有些程序的端口会和本应用冲突,所以要避开,例如sqlserver 2005 ,端口号: 1433 , oracle端口号 1521。
以下代码为客户端: activity
package com.lee.activity;
import com.lee.socket.ClientSocket;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
public class ClientActivity extends Activity {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
final EditText text = (EditText)this.findViewById(R.id.txtEdit);
final Button button = (Button)this.findViewById(R.id.btnSend);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
ClientSocket socket = new ClientSocket();
String str = text.getText().toString();
socket.send(str);
socket.close();
}
});
}
}
下面为socket发送
package com.lee.socket;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.net.Socket;
import java.net.UnknownHostException;
public class ClientSocket{
private Socket socket;
private final static String IPADDRESS = "192.168.0.101";
private final static int PORT = 9758;
public ClientSocket()
{
super();
if(socket == null)
{
try {
socket = new Socket(IPADDRESS, PORT);
System.out.println("连接建立成功: ip:"+ IPADDRESS +" port:"+PORT);
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
public void send(String msg)
{
try {
PrintWriter out = new PrintWriter(socket.getOutputStream());
out.println(msg);
out.flush();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
public synchronized void close()
{
try {
socket.close();
socket = null;
} catch (IOException e) {
e.printStackTrace();
}
}
}
最后,我们在manifest.xml文件中添加以下权限,以便android应用程序能够正常访问网络
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"></uses-permission>
<uses-permission android:name="android.permission.INTERNET"></uses-permission>