iOS中基於 Socket 的 C/S 結構網路通訊(中),iossocket

來源:互聯網
上載者:User

iOS中基於 Socket 的 C/S 結構網路通訊(中),iossocket

               結合上一篇的知識,接下來將介紹基於 TCP 協議的 Socket  編程;由於 Socket 需要有用戶端和服務端,那麼現在實現的是關於服務端的簡單程式。服務端採用的是CFStream 類來實現的。

     這個服務端是把Xcode中的 Command Line Tool 來作為服務端的;當然,你也可以把 iPhone 作為服務端,但是要利用其他的架構,比如 AsyncSocket (https://github.com/roustem/AsyncSocket) ,裡面有分為 UDP 和 TCP 實現的 Socket,來源程式裡也有許多關於資料流的操作,可以作為深入理解來用,當然也是比較複雜的。

     下面來看一下簡單實現的 TCP 服務端程式:(TCPServer.m)

<pre name="code" class="objc">#import <CoreFoundation/CoreFoundation.h>#include <sys/socket.h>#include <netinet/in.h>#define PORT 8734void AcceptCallBack(CFSocketRef, CFSocketCallBackType, CFDataRef, const void *, void *);void WriteStreamClientCallBack(CFWriteStreamRef stream, CFStreamEventType eventType, void *);void ReadStreamClientCallBack (CFReadStreamRef stream, CFStreamEventType eventType,void *);int main(int argc, const char * argv[]){    /* 定義一個Server Socket引用 */    CFSocketRef sserver;    /* 建立socket context */    CFSocketContext CTX = { 0, NULL, NULL, NULL, NULL };        /* 建立server socket  TCP IPv4 設定回呼函數 */    sserver = CFSocketCreate(NULL, PF_INET, SOCK_STREAM, IPPROTO_TCP,                             kCFSocketAcceptCallBack, (CFSocketCallBack)AcceptCallBack, &CTX);    if (sserver == NULL)        return -1;            /* 設定是否重新綁定標誌 */    int yes = 1;        /* 設定socket屬性 SOL_SOCKET是設定tcp SO_REUSEADDR是重新綁定,yes 是否重新綁定*/    setsockopt(CFSocketGetNative(sserver), SOL_SOCKET, SO_REUSEADDR,               (void *)&yes, sizeof(yes));        /* 設定連接埠和地址 */    struct sockaddr_in addr;    memset(&addr, 0, sizeof(addr));             //memset函數對指定的地址進行記憶體拷貝    addr.sin_len = sizeof(addr);    addr.sin_family = AF_INET;                  //AF_INET是設定 IPv4    addr.sin_port = htons(PORT);                //htons函數 無符號短整型數轉換成“網路位元組序”    addr.sin_addr.s_addr = htonl(INADDR_ANY);   //INADDR_ANY有核心分配,htonl函數 無符號長整型數轉換成“網路位元組序”            /* 從指定位元組緩衝區複製,一個不可變的CFData對象*/    CFDataRef address = CFDataCreate(kCFAllocatorDefault, (UInt8*)&addr, sizeof(addr));        /* 設定Socket*/    if (CFSocketSetAddress(sserver, (CFDataRef)address) != kCFSocketSuccess) {        fprintf(stderr, "Socket綁定失敗\n");        CFRelease(sserver);        return -1;    }        /* 建立一個Run Loop Socket源 */    CFRunLoopSourceRef sourceRef = CFSocketCreateRunLoopSource(kCFAllocatorDefault, sserver, 0);    /* Socket源添加到Run Loop中 */    CFRunLoopAddSource(CFRunLoopGetCurrent(), sourceRef, kCFRunLoopCommonModes);    CFRelease(sourceRef);        printf("Socket listening on port %d\n", PORT);    /* 運行Loop */    CFRunLoopRun();        }/* 接收用戶端請求後,回呼函數  */void AcceptCallBack(                    CFSocketRef socket,                    CFSocketCallBackType type,                    CFDataRef address,                    const void *data,                    void *info){    CFReadStreamRef readStream = NULL;    CFWriteStreamRef writeStream = NULL;        /* data 參數涵義是,如果是kCFSocketAcceptCallBack類型,data是CFSocketNativeHandle類型的指標 */    CFSocketNativeHandle sock = *(CFSocketNativeHandle *) data;        /* 建立讀寫Socket流 */    CFStreamCreatePairWithSocket(kCFAllocatorDefault, sock,                                 &readStream, &writeStream);        if (!readStream || !writeStream) {        close(sock);        fprintf(stderr, "CFStreamCreatePairWithSocket() 失敗\n");        return;    }        CFStreamClientContext streamCtxt = {0, NULL, NULL, NULL, NULL};    // 註冊兩種回呼函數    CFReadStreamSetClient(readStream, kCFStreamEventHasBytesAvailable, ReadStreamClientCallBack, &streamCtxt);    CFWriteStreamSetClient(writeStream, kCFStreamEventCanAcceptBytes, WriteStreamClientCallBack, &streamCtxt);        //加入到迴圈當中    CFReadStreamScheduleWithRunLoop(readStream, CFRunLoopGetCurrent(),kCFRunLoopCommonModes);    CFWriteStreamScheduleWithRunLoop(writeStream, CFRunLoopGetCurrent(),kCFRunLoopCommonModes);        CFReadStreamOpen(readStream);    CFWriteStreamOpen(writeStream);    }/* 讀取流操作 用戶端有資料過來時候調用 */void ReadStreamClientCallBack(CFReadStreamRef stream, CFStreamEventType eventType, void* clientCallBackInfo){        UInt8 buff[255];    CFReadStreamRef inputStream = stream;        if(NULL != inputStream)    {                CFReadStreamRead(stream, buff, 255);                printf("接受到資料:%s\n",buff);                CFReadStreamClose(inputStream);        CFReadStreamUnscheduleFromRunLoop(inputStream, CFRunLoopGetCurrent(),kCFRunLoopCommonModes);        inputStream = NULL;    }}/* 寫入流操作 用戶端在讀取資料時候調用 */void WriteStreamClientCallBack(CFWriteStreamRef stream, CFStreamEventType eventType, void* clientCallBackInfo){    CFWriteStreamRef    outputStream = stream;    //輸出    UInt8 buff[] = "你好,用戶端!";       //向用戶端發送的資訊    if(NULL != outputStream)    {        CFWriteStreamWrite(outputStream, buff, strlen((const char*)buff)+1);        //關閉輸出資料流        CFWriteStreamClose(outputStream);        CFWriteStreamUnscheduleFromRunLoop(outputStream, CFRunLoopGetCurrent(),kCFRunLoopCommonModes);        outputStream = NULL;    }}


               
此段程式只涉及比較簡單的資料流操作,詳細的資料流操作請參考 AsyncSocket 的源碼;至此,那麼一個服務端就已經實現了。


      未完待續......


什是socket網路?什是C-S結構?

通訊端Socket是指向基於網路的另一個應用程式的通訊連的引用。應用程式通常通過通訊端向網路發出請求或者答應網路請求。socket大致位於會話層。c/s結構就是客戶機伺服器模式。其中一台或者幾台較大的電腦集中進行共用資料庫的管理和存取,稱為伺服器。其他的應用處理工作分散到網路上其他電腦上進行。B/s就是中庸伺服器結構,由若干個微機工作站與一台或者多台檔案伺服器通過通訊鏈路串連。比如超市的收銀機。
 
使用Socket來編寫C/S結構的的程式,實現客戶器端發送“你好伺服器端接收,同時,伺服器端返回“你好客

下面這個是伺服器端
import java.net.*;
import java.io.*;

public class SocketTest {

public static void main(String[] args) throws Exception{
//boolean isquit=true;
InputStream is;
OutputStream os;
byte [] buf = new byte[20];
String str;
ServerSocket ss = new ServerSocket(8000);
//while(isquit) 這裡不注釋可以一直監聽
{
Socket s = ss.accept();
is=s.getInputStream();
os=s.getOutputStream();
is.read(buf);
str = new String(buf);
System.out.println(str);
os.write("你好,用戶端!".getBytes());
}

}
}
下面這個是用戶端
import java.net.*;
import java.io.*;

public class Client {

public Client() {
}

public static void main(String [] args) throws Exception
{
OutputStream os;
InputStream is;
byte [] buf = new byte[20];
String str;

Socket s = new Socket("127.0.0.1",8000);

os = s.getOutputStream();
is = s.getInputStream();

os.write("你好".getBytes());
is.read(buf);
str = new String(buf);
System.out.println(str);
}

}
有什麼問題可以繼續問我,QQ:517044170
 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.