Android之TCP服务器编程
推荐一个学java或C++的网站http://www.weixueyuan.net/,本来想自己学了总结出来再写博客,现在没时间,打字太慢!!!!,又想让这好东西让许多人知道。
关于网络通信:每一台电脑都有自己的ip地址,每台电脑上的网络应用程序都有自己的通信端口,张三的电脑(ip:192.168.1.110)上有一个网络应用程序A(通信端口5000),李四的电脑(ip:192.168.1.220)上有一个网络应用程序B(通信端口8000),张三给李四发消息,首先你要知道李四的ip地址,向指定的ip(李四ip:192.168.1.220)发信息,信息就发到了李四的电脑。再指定一下发送的端口号(通信端口8000),信息就发到了李四电脑的网络应用程序B上。
TCP--一种网络通信方式而已。分为服务器(网络应用程序)和客户端(网络应用程序),TCP通信过程,首先打开服务器,监听自己的网络通信端口(假设为9000),打开客户端,设置好要连接的ip地址和服务器的网络通信端口(9000),这样服务器一旦监听到网络通信端口有连接,二者就建立了连接。这是我写的TCP客服端的开头。直接拿过来了
因为是服务器所以在布局文件里放一个button用于启动服务器;一个button用于发送消息;放一个edittext用于监听端口;一个edittext用于接收消息;一个edittext用于发送消息(我会把源码放在最后,前面所显示的我可能会在上面涂鸦的!!!)
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context="com.Tcpserver.MainActivity" > <!-- 监听端口号 --> <TextView android:id="@+id/port_TextView" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="监听的端口:" /> <!-- 端口号 --> <EditText android:id="@+id/port_EditText" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="8080" android:layout_below="@id/port_TextView" /> <!-- 发送的消息 --> <TextView android:id="@+id/message_TextView" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="发送的消息" android:layout_below="@id/port_EditText"/> <!-- 发送消息框 --> <EditText android:id="@+id/message_EditText" android:layout_width="match_parent" android:layout_height="wrap_content" android:hint="输入要发送的消息:" android:layout_below="@id/message_TextView" /> <!-- 启动按钮 --> <Button android:id="@+id/start_button" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="启动服务" android:layout_below="@id/message_EditText" android:layout_alignParentLeft="true" /> <!-- 发送按钮 --> <Button android:id="@+id/send_button" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="发送消息" android:layout_below="@id/message_EditText" android:layout_alignParentRight="true" /> <!-- 接收的消息--> <TextView android:id="@+id/receive_TextView" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_below="@id/start_button" android:text="接收的消息:" /> <!-- 接收消息框 --> <EditText android:gravity="top"让消息每回都从编辑文本框的开头显示 android:id="@+id/receive_EditText" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_below="@id/receive_TextView" /> </RelativeLayout>
看一下java的api文档
所以呢 ServerSocket serversocket = new ServerSocket(8080);就完成了服务器的监听,
但是由于不让在主进程里启动监听所以就把它放在一个新的进程里吧。看一看下面代码
package com.Tcpserver; import java.io.IOException; import java.net.ServerSocket; import android.app.Activity; import android.net.wifi.WifiInfo; import android.net.wifi.WifiManager; import android.os.Bundle; import android.view.Menu; import android.view.MenuItem; import android.widget.Toast; public class MainActivity extends Activity { ServerSocket serverSocket;//创建ServerSocket @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); /** * 读一下手机wifi状态下的ip地址,只有知道它的ip才能连接它嘛 */ Toast.makeText(MainActivity.this, getLocalIpAddress(), Toast.LENGTH_SHORT).show(); /** * 启动服务器监听线程 */ ServerSocket_thread serversocket_thread = new ServerSocket_thread(); serversocket_thread.start(); } /** * 服务器监听线程 */ class ServerSocket_thread extends Thread { public void run()//重写Thread的run方法 { try { serverSocket = new ServerSocket(8080);//监听8080端口,这个程序的通信端口就是8080了 } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } /** * * 获取WIFI下ip地址 */ private String getLocalIpAddress() { WifiManager wifiManager = (WifiManager) getSystemService(WIFI_SERVICE); WifiInfo wifiInfo = wifiManager.getConnectionInfo(); // 获取32位整型IP地址 int ipAddress = wifiInfo.getIpAddress(); //返回整型地址转换成“*.*.*.*”地址 return String.format("%d.%d.%d.%d", (ipAddress & 0xff), (ipAddress >> 8 & 0xff), (ipAddress >> 16 & 0xff), (ipAddress >> 24 & 0xff)); } }
对了不要忘了加权限,一个wifi权限,一个internet权限,打开wifi和网络需要权限的
加权限过程
然后看一下
再贴一下代码吧,别忘了加权限,不然要么没反应要么显示xxxxx已停止运行
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.Tcpserver" android:versionCode="1" android:versionName="1.0" > <uses-sdk android:minSdkVersion="16" android:targetSdkVersion="21" /> <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/> <uses-permission android:name="android.permission.INTERNET"/> <application android:allowBackup="true" android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@style/AppTheme" > <activity android:name=".MainActivity" android:label="@string/app_name" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> </manifest>
好了我就把现在的下载到手机上
这样一打开这个软件便启动了监听,按钮,文本框什么的还没弄
好现在打开电脑上的网络调试助手
加点功能,点击启动服务器按钮后才启动服务,但是端口被我们定死了,,,,可不好玩,我们就设置连接的端口号为文本框中的端口号;
int port =Integer.valueOf(PortText.getText().toString());//获取端口号
package com.Tcpserver; import java.io.IOException; import java.net.ServerSocket; import android.app.Activity; import android.content.SharedPreferences.Editor; import android.net.wifi.WifiInfo; import android.net.wifi.WifiManager; import android.os.Bundle; import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.EditText; import android.widget.Toast; public class MainActivity extends Activity { ServerSocket serverSocket;//创建ServerSocket对象 Button startButton; EditText portEditText; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); /** * 读一下手机wifi状态下的ip地址,只有知道它的ip才能连接它嘛 */ Toast.makeText(MainActivity.this, getLocalIpAddress(), Toast.LENGTH_SHORT).show(); startButton = (Button) findViewById(R.id.start_button); portEditText = (EditText) findViewById(R.id.port_EditText); startButton.setOnClickListener(startButtonListener); } /** * 启动服务按钮监听事件 */ private OnClickListener startButtonListener = new OnClickListener() { @Override public void onClick(View v) { // TODO Auto-generated method stub /** * 启动服务器监听线程 */ ServerSocket_thread serversocket_thread = new ServerSocket_thread(); serversocket_thread.start(); } }; /** * 服务器监听线程 */ class ServerSocket_thread extends Thread { public void run()//重写Thread的run方法 { try { int port =Integer.valueOf(portEditText.getText().toString());//获取portEditText中的端口号 serverSocket = new ServerSocket(port);//监听port端口,这个程序的通信端口就是port了 } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } /** * * 获取WIFI下ip地址 */ private String getLocalIpAddress() { WifiManager wifiManager = (WifiManager) getSystemService(WIFI_SERVICE); WifiInfo wifiInfo = wifiManager.getConnectionInfo(); // 获取32位整型IP地址 int ipAddress = wifiInfo.getIpAddress(); //返回整型地址转换成“*.*.*.*”地址 return String.format("%d.%d.%d.%d", (ipAddress & 0xff), (ipAddress >> 8 & 0xff), (ipAddress >> 16 & 0xff), (ipAddress >> 24 & 0xff)); } }
接着,接收服务器发来的消息
对了有一点说错了是在
android 之TCP客户端编程 上的socket
其实socket这个类可以理解为(只要服务器和客服端建立连接就会建立socket),我们可以通过操作socket类中的方法得到我们想要的东西。感觉解释的也不咋的,不懂
package com.Tcpserver; import java.io.IOException; import java.io.InputStream; import java.net.ServerSocket; import java.net.Socket; import android.app.Activity; import android.content.SharedPreferences.Editor; import android.net.wifi.WifiInfo; import android.net.wifi.WifiManager; import android.os.Bundle; import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.EditText; import android.widget.Toast; public class MainActivity extends Activity { ServerSocket serverSocket;//创建ServerSocket对象 Socket clicksSocket;//连接通道,创建Socket对象 Button startButton; EditText portEditText; EditText receiveEditText; InputStream inputstream;//创建输入数据流 @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); /** * 读一下手机wifi状态下的ip地址,只有知道它的ip才能连接它嘛 */ Toast.makeText(MainActivity.this, getLocalIpAddress(), Toast.LENGTH_SHORT).show(); startButton = (Button) findViewById(R.id.start_button); portEditText = (EditText) findViewById(R.id.port_EditText); receiveEditText = (EditText) findViewById(R.id.receive_EditText); startButton.setOnClickListener(startButtonListener); } /** * 启动服务按钮监听事件 */ private OnClickListener startButtonListener = new OnClickListener() { @Override public void onClick(View v) { // TODO Auto-generated method stub /** * 启动服务器监听线程 */ ServerSocket_thread serversocket_thread = new ServerSocket_thread(); serversocket_thread.start(); } }; /** * 服务器监听线程 */ class ServerSocket_thread extends Thread { public void run()//重写Thread的run方法 { try { int port =Integer.valueOf(portEditText.getText().toString());//获取portEditText中的端口号 serverSocket = new ServerSocket(port);//监听port端口,这个程序的通信端口就是port了 } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } while (true) { try { //监听连接 ,如果无连接就会处于阻塞状态,一直在这等着 clicksSocket = serverSocket.accept(); inputstream = clicksSocket.getInputStream();//获取输入流 //启动接收线程 Receive_Thread receive_Thread = new Receive_Thread(); receive_Thread.start(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } } /** * * 接收线程 * */ class Receive_Thread extends Thread//继承Thread { public void run()//重写run方法 { while (true) { try { final byte[] buf = new byte[1024]; final int len = inputstream.read(buf); runOnUiThread(new Runnable() { public void run() { receiveEditText.setText(new String(buf,0,len)); } }); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } } } /** * * 获取WIFI下ip地址 */ private String getLocalIpAddress() { WifiManager wifiManager = (WifiManager) getSystemService(WIFI_SERVICE); WifiInfo wifiInfo = wifiManager.getConnectionInfo(); // 获取32位整型IP地址 int ipAddress = wifiInfo.getIpAddress(); //返回整型地址转换成“*.*.*.*”地址 return String.format("%d.%d.%d.%d", (ipAddress & 0xff), (ipAddress >> 8 & 0xff), (ipAddress >> 16 & 0xff), (ipAddress >> 24 & 0xff)); } }
runOnUiThread(new Runnable()
{
public void run()
{
receiveEditText.setText(new String(buf,0,len));
}
});
这个是因为不允许在其它线程里对组件进行操作,但是给了
runOnUiThread(new Runnable() { public void run() { //填写要操作的程序 } });
这种方法来对组件进行操作
最后一个发送消息
package com.Tcpserver; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.ServerSocket; import java.net.Socket; import android.app.Activity; import android.content.SharedPreferences.Editor; import android.net.wifi.WifiInfo; import android.net.wifi.WifiManager; import android.os.Bundle; import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.EditText; import android.widget.Toast; public class MainActivity extends Activity { ServerSocket serverSocket;//创建ServerSocket对象 Socket clicksSocket;//连接通道,创建Socket对象 Button startButton;//发送按钮 EditText portEditText;//端口号 EditText receiveEditText;//接收消息框 Button sendButton;//发送按钮 EditText sendEditText;//发送消息框 InputStream inputstream;//创建输入数据流 OutputStream outputStream;//创建输出数据流 @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); /** * 读一下手机wifi状态下的ip地址,只有知道它的ip才能连接它嘛 */ Toast.makeText(MainActivity.this, getLocalIpAddress(), Toast.LENGTH_SHORT).show(); startButton = (Button) findViewById(R.id.start_button); portEditText = (EditText) findViewById(R.id.port_EditText); receiveEditText = (EditText) findViewById(R.id.receive_EditText); sendButton = (Button) findViewById(R.id.send_button); sendEditText = (EditText) findViewById(R.id.message_EditText); startButton.setOnClickListener(startButtonListener); sendButton.setOnClickListener(sendButtonListener); } /** * 启动服务按钮监听事件 */ private OnClickListener startButtonListener = new OnClickListener() { @Override public void onClick(View v) { // TODO Auto-generated method stub /** * 启动服务器监听线程 */ ServerSocket_thread serversocket_thread = new ServerSocket_thread(); serversocket_thread.start(); } }; /** * 服务器监听线程 */ class ServerSocket_thread extends Thread { public void run()//重写Thread的run方法 { try { int port =Integer.valueOf(portEditText.getText().toString());//获取portEditText中的端口号 serverSocket = new ServerSocket(port);//监听port端口,这个程序的通信端口就是port了 } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } while (true) { try { //监听连接 ,如果无连接就会处于阻塞状态,一直在这等着 clicksSocket = serverSocket.accept(); inputstream = clicksSocket.getInputStream();// //启动接收线程 Receive_Thread receive_Thread = new Receive_Thread(); receive_Thread.start(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } } /** * * 接收线程 * */ class Receive_Thread extends Thread//继承Thread { public void run()//重写run方法 { while (true) { try { final byte[] buf = new byte[1024]; final int len = inputstream.read(buf); runOnUiThread(new Runnable() { public void run() { receiveEditText.setText(new String(buf,0,len)); } }); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } } } /** * 发送消息按钮事件 */ private OnClickListener sendButtonListener = new OnClickListener() { @Override public void onClick(View v) { // TODO Auto-generated method stub try { //获取输出流 outputStream = clicksSocket.getOutputStream(); //发送数据 outputStream.write(sendEditText.getText().toString().getBytes()); //outputStream.write("0".getBytes()); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } }; /** * * 获取WIFI下ip地址 */ private String getLocalIpAddress() { WifiManager wifiManager = (WifiManager) getSystemService(WIFI_SERVICE); WifiInfo wifiInfo = wifiManager.getConnectionInfo(); // 获取32位整型IP地址 int ipAddress = wifiInfo.getIpAddress(); //返回整型地址转换成“*.*.*.*”地址 return String.format("%d.%d.%d.%d", (ipAddress & 0xff), (ipAddress >> 8 & 0xff), (ipAddress >> 16 & 0xff), (ipAddress >> 24 & 0xff)); } }
布局源码
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context="com.Tcpserver.MainActivity" > <!-- 监听端口号 --> <TextView android:id="@+id/port_TextView" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="监听的端口:" /> <!-- 端口号 --> <EditText android:id="@+id/port_EditText" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="8080" android:layout_below="@id/port_TextView" /> <!-- 发送的消息 --> <TextView android:id="@+id/message_TextView" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="发送的消息" android:layout_below="@id/port_EditText"/> <!-- 发送消息框 --> <EditText android:id="@+id/message_EditText" android:layout_width="match_parent" android:layout_height="wrap_content" android:hint="输入要发送的消息:" android:layout_below="@id/message_TextView" /> <!-- 启动按钮 --> <Button android:id="@+id/start_button" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="启动服务" android:layout_below="@id/message_EditText" android:layout_alignParentLeft="true" /> <!-- 发送按钮 --> <Button android:id="@+id/send_button" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="发送消息" android:layout_below="@id/message_EditText" android:layout_alignParentRight="true" /> <!-- 接收的消息--> <TextView android:id="@+id/receive_TextView" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_below="@id/start_button" android:text="接收的消息:" /> <!-- 接收消息框 --> <EditText android:gravity="top" android:id="@+id/receive_EditText" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_below="@id/receive_TextView" /> </RelativeLayout>
。java源码
package com.Tcpserver; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.ServerSocket; import java.net.Socket; import android.app.Activity; import android.content.SharedPreferences.Editor; import android.net.wifi.WifiInfo; import android.net.wifi.WifiManager; import android.os.Bundle; import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.EditText; import android.widget.Toast; public class MainActivity extends Activity { ServerSocket serverSocket;//创建ServerSocket对象 Socket clicksSocket;//连接通道,创建Socket对象 Button startButton;//发送按钮 EditText portEditText;//端口号 EditText receiveEditText;//接收消息框 Button sendButton;//发送按钮 EditText sendEditText;//发送消息框 InputStream inputstream;//创建输入数据流 OutputStream outputStream;//创建输出数据流 @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); /** * 读一下手机wifi状态下的ip地址,只有知道它的ip才能连接它嘛 */ Toast.makeText(MainActivity.this, getLocalIpAddress(), Toast.LENGTH_SHORT).show(); startButton = (Button) findViewById(R.id.start_button); portEditText = (EditText) findViewById(R.id.port_EditText); receiveEditText = (EditText) findViewById(R.id.receive_EditText); sendButton = (Button) findViewById(R.id.send_button); sendEditText = (EditText) findViewById(R.id.message_EditText); startButton.setOnClickListener(startButtonListener); sendButton.setOnClickListener(sendButtonListener); } /** * 启动服务按钮监听事件 */ private OnClickListener startButtonListener = new OnClickListener() { @Override public void onClick(View v) { // TODO Auto-generated method stub /** * 启动服务器监听线程 */ ServerSocket_thread serversocket_thread = new ServerSocket_thread(); serversocket_thread.start(); } }; /** * 服务器监听线程 */ class ServerSocket_thread extends Thread { public void run()//重写Thread的run方法 { try { int port =Integer.valueOf(portEditText.getText().toString());//获取portEditText中的端口号 serverSocket = new ServerSocket(port);//监听port端口,这个程序的通信端口就是port了 } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } while (true) { try { //监听连接 ,如果无连接就会处于阻塞状态,一直在这等着 clicksSocket = serverSocket.accept(); inputstream = clicksSocket.getInputStream();// //启动接收线程 Receive_Thread receive_Thread = new Receive_Thread(); receive_Thread.start(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } } /** * * 接收线程 * */ class Receive_Thread extends Thread//继承Thread { public void run()//重写run方法 { while (true) { try { final byte[] buf = new byte[1024]; final int len = inputstream.read(buf); runOnUiThread(new Runnable() { public void run() { receiveEditText.setText(new String(buf,0,len)); } }); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } } } /** * 发送消息按钮事件 */ private OnClickListener sendButtonListener = new OnClickListener() { @Override public void onClick(View v) { // TODO Auto-generated method stub try { //获取输出流 outputStream = clicksSocket.getOutputStream(); //发送数据 outputStream.write(sendEditText.getText().toString().getBytes()); //outputStream.write("0".getBytes()); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } }; /** * * 获取WIFI下ip地址 */ private String getLocalIpAddress() { WifiManager wifiManager = (WifiManager) getSystemService(WIFI_SERVICE); WifiInfo wifiInfo = wifiManager.getConnectionInfo(); // 获取32位整型IP地址 int ipAddress = wifiInfo.getIpAddress(); //返回整型地址转换成“*.*.*.*”地址 return String.format("%d.%d.%d.%d", (ipAddress & 0xff), (ipAddress >> 8 & 0xff), (ipAddress >> 16 & 0xff), (ipAddress >> 24 & 0xff)); } }
,,,,,源码
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.Tcpserver" android:versionCode="1" android:versionName="1.0" > <uses-sdk android:minSdkVersion="16" android:targetSdkVersion="21" /> <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/> <uses-permission android:name="android.permission.INTERNET"/> <application android:allowBackup="true" android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@style/AppTheme" > <activity android:name=".MainActivity" android:label="@string/app_name" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> </manifest>
好了,一些提示,或者其它什么的亲们自己弄吧。可以看看我的android客服端的,我要吃饭去了