IOS到Android,反之亦然,使用套接字的TCP服务器客户端连接 [英] IOS to Android and vice versa TCP server client connection using sockets

查看:28
本文介绍了IOS到Android,反之亦然,使用套接字的TCP服务器客户端连接的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经成功地实现了从 android 到 ios 的 tcp 服务器客户端设置,Android 是 tcp 服务器,ios 是客户端,我从 tcp 服务器处理客户端,但是我面临着将 ios 作为服务器端和 android 做同样的问题客户端客户端 android 连接到 ios 服务器,但我不知道如何在连接 android 设备后从 ios 服务器端向 android 客户端发送消息,感谢任何帮助

i have successfully implemented a tcp server client setup from android to ios Android being the tcp server and ios being the client i handle the client from the tcp server but am facing problems doing the same with ios as the server side and android the client The clent android connects to the ios server but i do not know how to send messages from the ios server side to the android client once the android device is connected any help appreciated

下图是建立tcp服务器的代码

shown below is the code for establishing a tcp server

#import "TCPServer.h"

#include <sys/socket.h>

#include <netinet/in.h>

#include <unistd.h>

#include <CFNetwork/CFSocketStream.h>

NSString * const TCPServerErrorDomain = @"TCPServerErrorDomain";

@interface TCPServer ()

@property(assign) uint16_t port;

@property (nonatomic, strong, readwrite) NSOutputStream *       outputStream;

@end

@implementation TCPServer

@synthesize delegate=_delegate, port=_port;

- (id)init {

    return self;

}

- (void)dealloc {

    [self stop];

    [super dealloc];
}

- (void)handleNewConnectionFromAddress:(NSData *)addr inputStream:(NSInputStream *)istr outputStream:(NSOutputStream *)ostr {

     self.outputStream = ostr;

    UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"Port"
                                                        message:@"Received Connection"
                                                       delegate:self
                                              cancelButtonTitle:@"Ok"
                                              otherButtonTitles:nil, nil];

 [alertView performSelectorOnMainThread:@selector(show) withObject:nil waitUntilDone:YES];


    if (self.delegate && [self.delegate respondsToSelector:@selector(didAcceptConnectionForServer:inputStream:outputStream:)])
 {

        [self.delegate didAcceptConnectionForServer:self inputStream:istr outputStream:ostr];

    }
}

// This function is called by CFSocket when a new connection comes in.

// We gather some data here, and convert the function call to a method

// invocation on TCPServer.
static void TCPServerAcceptCallBack(CFSocketRef socket, CFSocketCallBackType type, CFDataRef address, const void *data, void *info)
 {

    TCPServer *server = (TCPServer *)info;

    if (kCFSocketAcceptCallBack == type) {

  // for an AcceptCallBack, the data parameter is a pointer to a CFSocketNativeHandle

        CFSocketNativeHandle nativeSocketHandle = *(CFSocketNativeHandle *)data;

        uint8_t name[SOCK_MAXADDRLEN];

        socklen_t namelen = sizeof(name);

        NSData *peer = nil;

        if (0 == getpeername(nativeSocketHandle, (struct sockaddr *)name, &namelen)) {

            peer = [NSData dataWithBytes:name length:namelen];

        }

        CFReadStreamRef readStream = NULL;

        CFWriteStreamRef writeStream = NULL;

        CFStreamCreatePairWithSocket(kCFAllocatorDefault, nativeSocketHandle, &readStream,   &writeStream);

        if (readStream && writeStream) {

            CFReadStreamSetProperty(readStream, kCFStreamPropertyShouldCloseNativeSocket, 
     kCFBooleanTrue);

         CFWriteStreamSetProperty(writeStream, kCFStreamPropertyShouldCloseNativeSocket, kCFBooleanTrue);



           // NSData *data = [[NSData alloc] initWithData:[@"next" dataUsingEncoding:NSASCIIStringEncoding]];
          //  [(NSOutputStream *)writeStream write:[data bytes] maxLength:[data length]];



            [server handleNewConnectionFromAddress:peer inputStream:(NSInputStream *)readStream outputStream:(NSOutputStream *)writeStream];
        } 
    else {
            // on any failure, need to destroy the CFSocketNativeHandle
            // since we are not going to use it any more
            close(nativeSocketHandle);
        }
        if (readStream) CFRelease(readStream);
        if (writeStream) CFRelease(writeStream);
    }
}

- (BOOL)start:(NSError **)error {

      NSLog(@"Called start");

    CFSocketContext socketCtxt = {0, self, NULL, NULL, NULL};

    // Start by trying to do everything with IPv6.  This will work for both IPv4 and IPv6 clients
    // via the miracle of mapped IPv4 addresses.

    witap_socket = CFSocketCreate(kCFAllocatorDefault, PF_INET6, SOCK_STREAM, IPPROTO_TCP, kCFSocketAcceptCallBack, (CFSocketCallBack)&TCPServerAcceptCallBack, &socketCtxt);

    if (witap_socket != NULL)   // the socket was created successfully
        protocolFamily = PF_INET6;
    else { // there was an error creating the IPv6 socket - could be running under iOS 3.x
        witap_socket = CFSocketCreate(kCFAllocatorDefault, PF_INET, SOCK_STREAM, IPPROTO_TCP, kCFSocketAcceptCallBack, (CFSocketCallBack)&TCPServerAcceptCallBack, &socketCtxt);
        if (witap_socket != NULL)
            protocolFamily = PF_INET;
    }

    if (NULL == witap_socket) {
        if (error) *error = [[NSError alloc] initWithDomain:TCPServerErrorDomain code:kTCPServerNoSocketsAvailable userInfo:nil];
        if (witap_socket) CFRelease(witap_socket);
        witap_socket = NULL;
        return NO;
    }

    int yes = 1;
    setsockopt(CFSocketGetNative(witap_socket), SOL_SOCKET, SO_REUSEADDR, (void *)&yes, sizeof(yes));

    // set up the IP endpoint; use port 0, so the kernel will choose an arbitrary port for us, which will be advertised using Bonjour
    if (protocolFamily == PF_INET6) {
        struct sockaddr_in6 addr6;
        memset(&addr6, 0, sizeof(addr6));
        addr6.sin6_len = sizeof(addr6);
        addr6.sin6_family = AF_INET6;
        addr6.sin6_port = 0;
        addr6.sin6_flowinfo = 0;
        addr6.sin6_addr = in6addr_any;
        NSData *address6 = [NSData dataWithBytes:&addr6 length:sizeof(addr6)];

        if (kCFSocketSuccess != CFSocketSetAddress(witap_socket, (CFDataRef)address6)) {
            if (error) *error = [[NSError alloc] initWithDomain:TCPServerErrorDomain code:kTCPServerCouldNotBindToIPv6Address userInfo:nil];
            if (witap_socket) CFRelease(witap_socket);
            witap_socket = NULL;
            return NO;
        }

        // now that the binding was successful, we get the port number
        // -- we will need it for the NSNetService
        NSData *addr = [(NSData *)CFSocketCopyAddress(witap_socket) autorelease];
        memcpy(&addr6, [addr bytes], [addr length]);
        self.port = ntohs(addr6.sin6_port);


        UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"Port"
                                                            message:[NSString stringWithFormat:@"Port %hu",self.port]
                                                           delegate:self
                                                  cancelButtonTitle:@"Ok"
                                                  otherButtonTitles:nil, nil];
        [alertView performSelectorOnMainThread:@selector(show) withObject:nil waitUntilDone:YES];

    } else {
        struct sockaddr_in addr4;
        memset(&addr4, 0, sizeof(addr4));
        addr4.sin_len = sizeof(addr4);
        addr4.sin_family = AF_INET;
        addr4.sin_port = 0;
        addr4.sin_addr.s_addr = htonl(INADDR_ANY);
        NSData *address4 = [NSData dataWithBytes:&addr4 length:sizeof(addr4)];

        if (kCFSocketSuccess != CFSocketSetAddress(witap_socket, (CFDataRef)address4)) {
  if (error) *error = [[NSError alloc] initWithDomain:TCPServerErrorDomain code:kTCPServerCouldNotBindToIPv4Address userInfo:nil];
            if (witap_socket) CFRelease(witap_socket);
            witap_socket = NULL;
            return NO;
        }

        // now that the binding was successful, we get the port number
        // -- we will need it for the NSNetService
        NSData *addr = [(NSData *)CFSocketCopyAddress(witap_socket) autorelease];
        memcpy(&addr4, [addr bytes], [addr length]);
        self.port = ntohs(addr4.sin_port);
    }

    // set up the run loop sources for the sockets
    CFRunLoopRef cfrl = CFRunLoopGetCurrent();
    CFRunLoopSourceRef source = CFSocketCreateRunLoopSource(kCFAllocatorDefault,witap_socket, 0);
    CFRunLoopAddSource(cfrl, source, kCFRunLoopCommonModes);
    CFRelease(source);

    return YES;
}

- (BOOL)stop {

    if (witap_socket) {
        CFSocketInvalidate(witap_socket);
        CFRelease(witap_socket);
        witap_socket = NULL;
    }

    return YES;
}

-(void)SendMessage:(NSString *)message
{
  NSData *data = [[NSData alloc] initWithData:[message dataUsingEncoding:NSASCIIStringEncoding]];

[self.outputStream write:[data bytes] maxLength:[data length]];

}

@end

问题是一旦我使用此代码连接到服务器

The question is once i am connected to the server using this code

- (void) initNetworkCommunication {

    CFReadStreamRef readStream;
    CFWriteStreamRef writeStream;
    CFStreamCreatePairWithSocketToHost(NULL, (CFStringRef)@"192.168.1.44",60189, &readStream, &writeStream);

    inputStream = (NSInputStream *)readStream;
    outputStream = (NSOutputStream *)writeStream;
    [inputStream setDelegate:self];
    [outputStream setDelegate:self];
    [inputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
    [outputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
    [inputStream open];
    [outputStream open];    
}

如何从服务器向客户端发送消息?

How do i send a message from the server to the client?

推荐答案

我能够在打开输出流 (NSOutputStream) 后发送消息我面临的唯一问题是只有当我关闭输出流时 android 才能接收消息谁能告诉我哪里出错了

I was able to send messages after i opened the output stream (NSOutputStream) the only problem i am facing is android receives messages only when i close my output stream can any one tell me where i am going wrong

android的客户端代码如下

the client code for android is as follows

package com.example.remoteapp;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.Socket;
import android.util.Log;



public class TCPClient {

    private String serverMessage;
    /**
     * Specify the Server Ip Address here. Whereas our Socket Server is started.
     * */
//public static final String SERVERIP = "192.168.43.1"; // fixed IP address for hotspot
    public static final String SERVERIP = "192.168.1.44"; //computer ip address

   //public static final int SERVERPORT = 4321;
    public static final int SERVERPORT = 57917;
    private OnMessageReceived mMessageListener = null;
    private boolean mRun = false;

    private PrintWriter out = null;
    private BufferedReader in = null;

    /**
     *  Constructor of the class. OnMessagedReceived listens for the messages received from server
     */
    public TCPClient(final OnMessageReceived listener) 
    {
        mMessageListener = listener;
    }

    /**
     * Sends the message entered by client to the server
     * @param message text entered by client
     */
    public void sendMessage(String message){
        if (out != null && !out.checkError()) {
            System.out.println("message: "+ message);
          //  out.println(message);
           // out.flush();
        }
    }

    public void stopClient(){
        mRun = false;
    }

    public void run() {

        mRun = true;

        try {
            //here you must put your computer's IP address.
            InetAddress serverAddr = InetAddress.getByName(SERVERIP);

            Log.e("TCP SI Client", "SI: Connecting...");

            //create a socket to make the connection with the server
            Socket socket = new Socket(serverAddr, SERVERPORT);
            try {

                //send the message to the server
                out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())), true);

                Log.e("TCP SI Client", "SI: Sent.");

                Log.e("TCP SI Client", "SI: Done.");

                sendMessage("initial message");
                //receive the message which the server sends back
                in = new BufferedReader(new InputStreamReader(socket.getInputStream()));

                //in this while the client listens for the messages sent by the server
                while (mRun) {
                    serverMessage = in.readLine();

                    if (serverMessage != null && mMessageListener != null) {
                        //call the method messageReceived from MyActivity class
                        mMessageListener.messageReceived(serverMessage);
                        Log.e("RESPONSE FROM SERVER", "S: Received Message: '" + serverMessage + "'");
                    }
                    serverMessage = null;
                }
            }
            catch (Exception e) 
            {
                Log.e("TCP SI Error", "SI: Error", e);
                e.printStackTrace();
            }
            finally 
            {
                //the socket must be closed. It is not possible to reconnect to this socket
                // after it is closed, which means a new socket instance has to be created.
                socket.close();
            }

        } catch (Exception e) {

            Log.e("TCP SI Error", "SI: Error", e);

        }

    }

    //Declare the interface. The method messageReceived(String message) will must be implemented in the MyActivity
    //class at on asynckTask doInBackground
    public interface OnMessageReceived {
        public void messageReceived(String message);
    }
}

这篇关于IOS到Android,反之亦然,使用套接字的TCP服务器客户端连接的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆