首先,我不是C#程序员,所以请原谅我从MSDN examples page复制粘贴一个C#套接字客户端。
基本上,如果您想通过USB与Android应用程序通信,您需要通过adb(Android调试桥)指示您的手机创建端口转发,然后您可以使用普通的TCP/IP套接字建立流通信与您的客户。
首先,您必须在您的 PC 上安装正确的驱动程序(您可以在您的制造商网站上找到它们),这样当您运行 adb devices 时,您的手机就会被正确识别:
C:\adt-bundle-windows-x86-20140321\sdk\platform-tools>adb devices
List of devices attached
039d78fa2518e606 device
接下来您需要在 Android 端设置端口转发,以便您 PC 上本地主机上的套接字连接将正确转发到手机上的本地主机。这也是通过adb 完成的:
C:\adt-bundle-windows-x86-20140321\sdk\platform-tools>adb forward tcp:6000 tcp:6000
验证是否成功:
C:\adt-bundle-windows-x86-20140321\sdk\platform-tools>adb forward --list
039d78fa2518e606 tcp:6000 tcp:6000
现在您可以在 Android 端创建一个常规的套接字服务器应用程序。我很抱歉这个例子非常简单(我很晚才注意到这个问题,没有时间实现正确的通信协议)。但这应该向您展示如何在客户端和主机之间传输字符串,并且您可以实现必要的循环,或者如果需要更复杂的传输协议。
基本上这只是默认的 Android 项目,添加了 1 个类,在单独的线程中运行(GUI 和网络活动不能在同一线程中运行)。
所以,我们的 MainActivity.java 看起来像这样:
package com.example.dataexchange;
import android.support.v7.app.ActionBarActivity;
import android.support.v7.app.ActionBar;
import android.support.v4.app.Fragment;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.os.Build;
public class MainActivity extends ActionBarActivity {
SocketHandler server;
@Override
protected void onCreate(Bundle savedInstanceState) {
Log.v("jlumme", "Main/ start network task");
new Thread(new Runnable() {
public void run() {
server = new SocketHandler(6000);
server.run();
}
}).start();
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (savedInstanceState == null) {
getSupportFragmentManager().beginTransaction()
.add(R.id.container, new PlaceholderFragment())
.commit();
}
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
/**
* A placeholder fragment containing a simple view.
*/
public static class PlaceholderFragment extends Fragment {
public PlaceholderFragment() {
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_main, container, false);
return rootView;
}
}
}
通常的东西,我们只是在一个单独的线程中启动我们的SocketHandler 类。 SocketThread 类如下所示:
package com.example.dataexchange;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import android.util.Log;
public class SocketHandler implements Runnable {
private Socket socket;
private ServerSocket server;
private PrintWriter out;
private BufferedReader in;
private int socketPort;
SocketHandler(int port) {
socketPort = port;
}
@Override
public void run() {
Log.v("jlumme", "Socket thread has started");
String inputText;
// TODO Auto-generated method stub
try {
Log.v("jlumme", "Starting socket server ");
server = new ServerSocket(6000);
socket = server.accept();
Log.v("jlumme", "Client connected");
out = new PrintWriter( new BufferedWriter( new OutputStreamWriter(socket.getOutputStream())),true);
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
while ((inputText = in.readLine()) != null) {
Log.v("jlumme", "Received:" + inputText);
out.println("you wrote:" + inputText);
}
Log.v("jlumme", "connection established");
} catch (IOException ioe) {
ioe.printStackTrace();
}
}
}
基本上在run() 方法中,您启动一个新的SocketServer,并开始等待客户。客户端连接后,您可以双向设置流缓冲区,并开始等待消息(任何以换行符结尾的,'\n' 都可以)。
在 C# 方面,应用程序非常简单。它连接到localhost 端口6000 并发送一行:
using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
public class SynchronousSocketClient
{
public static void StartClient() {
// Data buffer for incoming data.
byte[] bytes = new byte[1024];
// Connect to a remote device.
try {
IPEndPoint remoteEP = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 6000);
// Create a TCP/IP socket.
Socket sender = new Socket(AddressFamily.InterNetwork,
SocketType.Stream, ProtocolType.Tcp );
// Connect the socket to the remote endpoint. Catch any errors.
try {
sender.Connect(remoteEP);
Console.WriteLine("Socket connected to {0}",
sender.RemoteEndPoint.ToString());
// Encode the data string into a byte array.
byte[] msg = Encoding.ASCII.GetBytes("This is a test\n");
// Send the data through the socket.
int bytesSent = sender.Send(msg);
// Receive the response from the remote device.
int bytesRec = sender.Receive(bytes);
Console.WriteLine("Echoed test = {0}",
Encoding.ASCII.GetString(bytes,0,bytesRec));
// Release the socket.
sender.Shutdown(SocketShutdown.Both);
sender.Close();
} catch (ArgumentNullException ane) {
Console.WriteLine("ArgumentNullException : {0}",ane.ToString());
} catch (SocketException se) {
Console.WriteLine("SocketException : {0}",se.ToString());
} catch (Exception e) {
Console.WriteLine("Unexpected exception : {0}", e.ToString());
}
} catch (Exception e) {
Console.WriteLine( e.ToString());
}
}
public static int Main(String[] args)
{
StartClient();
return 0;
}
}
如果在执行C#程序时,会发送this is a test字符串给客户端,客户端会回显:
c:\Visual Studio 2013\Projects\ConsoleApplication2\ConsoleApplication2\bin\Debug>ConsoleApplication2.exe
Socket connected to 127.0.0.1:6000
Echoed test = you wrote:This is a test
我想在赏金关闭之前达到最后期限,所以目前没有适当的消息处理,并且 c# 将立即退出(而 Android 端会对此感到困惑),对此我深表歉意。但是我认为一旦你运行了这个例子,你就可以很容易地将它扩展到你的需要,并实现必要的逻辑来处理终止和其他东西..
希望对你有帮助