簡體   English   中英

Socket-C服務器,Android客戶端

[英]Socket - C server , Android client

你好,我做了一個C服務器和一個用Java制作的Android客戶端。 ,即時通訊試圖讓服務器發送字符串振動並使手機振動一段時間。 我可以看到客戶端已連接,但我認為服務器實際上根本不發送任何數據,在按Enter鍵退出getchar()程序后,此錯誤會在logcat中彈出。

logcat錯誤

01-28 14:10:50.400: W/System.err(30663): java.net.SocketException: recvfrom failed: ECONNRESET (Connection reset by peer)
01-28 14:10:50.400: W/System.err(30663):    at libcore.io.IoBridge.maybeThrowAfterRecvfrom(IoBridge.java:552)
01-28 14:10:50.400: W/System.err(30663):    at libcore.io.IoBridge.recvfrom(IoBridge.java:516)
01-28 14:10:50.400: W/System.err(30663):    at java.net.PlainSocketImpl.read(PlainSocketImpl.java:488)
01-28 14:10:50.400: W/System.err(30663):    at java.net.PlainSocketImpl.access$000(PlainSocketImpl.java:46)
01-28 14:10:50.400: W/System.err(30663):    at java.net.PlainSocketImpl$PlainSocketInputStream.read(PlainSocketImpl.java:240)
01-28 14:10:50.400: W/System.err(30663):    at java.io.InputStreamReader.read(InputStreamReader.java:244)
01-28 14:10:50.410: W/System.err(30663):    at java.io.BufferedReader.fillBuf(BufferedReader.java:130)
01-28 14:10:50.410: W/System.err(30663):    at java.io.BufferedReader.readLine(BufferedReader.java:390)
01-28 14:10:50.410: W/System.err(30663):    at com.example.rat.RatService$ClientThread.run(RatService.java:76)
01-28 14:10:50.410: W/System.err(30663):    at java.lang.Thread.run(Thread.java:864)
01-28 14:10:50.410: W/System.err(30663): Caused by: libcore.io.ErrnoException: recvfrom failed: ECONNRESET (Connection reset by peer)
01-28 14:10:50.420: W/System.err(30663):    at libcore.io.Posix.recvfromBytes(Native Method)
01-28 14:10:50.420: W/System.err(30663):    at libcore.io.Posix.recvfrom(Posix.java:131)
01-28 14:10:50.420: W/System.err(30663):    at libcore.io.BlockGuardOs.recvfrom(BlockGuardOs.java:164)
01-28 14:10:50.420: W/System.err(30663):    at libcore.io.IoBridge.recvfrom(IoBridge.java:513)
01-28 14:10:50.420: W/System.err(30663):    ... 8 more

C服務器代碼。

int main(int argc, char *argv[])
{
  WSADATA wsa;
  SOCKET s, new_socket;
  struct sockaddr_in server, client;
  int c;
  char *message;

  if (WSAStartup(MAKEWORD(2, 2), &wsa) != 0)
  {
    printf("ERROR initlizaing winsock2 dll : %d", WSAGetLastError());
    return 1; // exit program with error.
  }

  printf("INitialised.\n");

  // create a socket
  s = socket(AF_INET, SOCK_STREAM, 0);
  if (s == INVALID_SOCKET)
  {
    printf("error at creating socket :%d", WSAGetLastError());
    WSACleanup();
    return 1;
  }

  printf("socket created");

  //Sockad_addr in strucsture prepare
  memset(&server, 0, sizeof server);
  server.sin_family = AF_INET;
  server.sin_addr.s_addr = INADDR_ANY;
  server.sin_port = htons(5000);

  // bind the socket

  if (bind(s, (struct sockaddr *) &server, sizeof(server)) == SOCKET_ERROR)
  {
    printf("Bind fialed with errror code : %d", WSAGetLastError());
    closesocket(s);
    WSACleanup();
    return 1;
  }

  listen(s, 3);

  printf("waiting for incoming connections");
  // this part is what i dont understand.
  c = sizeof(struct sockaddr_in);
  new_socket = accept(s, (struct sockaddr *) &client, &c);
  if (new_socket == INVALID_SOCKET)
  {
    printf("accept fialed with error code : %d", WSAGetLastError());

    closesocket(s);
    WSACleanup();
    return 1;
  }

  printf("Connection acceptëd");

  //reply to CLIENTCREATESTRUCT
  message = "vibrate";
  send(new_socket, message, strlen(message), 0);
  getchar();
  closesocket(s);
  WSACleanup();
  return 0;
}

ANdroid Java客戶端,

public class Service extends Service{
    private boolean isRunning = false;
    private static final  String SERVER_IP = "192.168.178.11";
    private static final int SERVERPORT = 5000;
    private Socket socket;
    Thread ClientThread = null;
    String st = null;



    public void onCreate() {

    }


    public int onStartCommand(Intent intent, int flags, int startId){
        super.onStartCommand(intent, flags, startId);

        // Annoucment about starting serivce

        // Start a Thread Called MyThread
        isRunning = true;
        this.ClientThread = new Thread(new ClientThread());
        this.ClientThread.start();

        // Keep running until it explicitly stopped.
        // stopped so returns sicky
        return START_STICKY;
    }
    // code


    public void onDestroy(){
        super.onDestroy();
        // stop background Thread
        isRunning = false;


    }

    public class ClientThread implements Runnable {
        public void run() {


            try{
                InetAddress serverAddr = InetAddress.getByName(SERVER_IP);

                socket = new Socket(serverAddr,SERVERPORT);


                BufferedReader input =  new BufferedReader(new InputStreamReader(socket.getInputStream()));


                String st = input.readLine();

                if (st.equals("vibrate")){
                    Vibrator v = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE);
                    v.vibrate(3000);
                }
                st = null;

            } catch (Exception e) {
                e.printStackTrace();
            }
        } 
    }

    @Override
    public IBinder onBind(Intent intent) {
        // TODO Auto-generated method stub
        return null;
    }
}

Android客戶端清單

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.rat"
    android:versionCode="1"
    android:versionName="1.0" >
    <uses-permission android:name="android.permission.VIBRATE" />
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-sdk
        android:minSdkVersion="8"
        android:targetSdkVersion="19" />

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name="com.example.Service.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>
        <service android:name=".Service" />
    </application>

</manifest>

BufferedReader.readLine()阻塞,直到收到換行為止。

BufferedReader的文檔

讀取一行文本。 一行被認為由換行符('\\ n'),回車符('\\ r')或回車符后立即換行符中的任何一個終止。

因此,要解決此問題,只需使服務器通過更改以下行來發送換行符:

message = "vibrate";

成為:

message = "vibrate\n";

更新:

客戶端記錄的錯誤消息清楚地表明服務器由於結束而關閉了連接。

這意味着send()已返回。 知道send()返回了哪個值會很有趣。

因此,我建議您修改這一行:

send(new_socket, message, strlen(message), 0);

成為:

{
  int result = send(new_socket, message, strlen(message), 0);

  if (SOCKET_ERROR == result)
  {
    fprintf(stderr, "send() failed with error code: %d\n", WSAGetLastError());
  }
  else
  {
    fprintf(stderr, "Sent %d bytes out of %u.\n", result, strlen(message));
  }
}

您可以嘗試java.util.Scanner讀取java.io.BufferedReader之類的 jut,我的意思是:

java.util.Scanner sc = new java.util.Scanner(socket.getInputStream(), "US-ASCII").useDelimiter("\\n");
String st = sc.nextLine();
if (st.equals("vibrate")){
    // ...
}

在服務器中,您必須添加換行符:

message = "vibrate\n";

注意:如果要將分隔符從“ \\ n”更改為其他任何字符,只需在useDelimiter上指定並將其添加到服務器上的消息中即可。

注意:這是Scanner與BufferedReader之間的比較。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM