即時通信(II)

Socket 鏈接Demo

Socket客戶端代碼

  1 #import "ViewController.h"
  2 //0、導入頭文件
  3 #include <netinet/in.h>
  4 #include <sys/socket.h>
  5 #include <arpa/inet.h>
  6 
  7 static const char *serevr_ip = "127.0.0.1";
  8 static const short server_port = 6969;
  9 
 10 @interface ViewController ()
 11 
 12 @property (assign, nonatomic) int clientSocket;
 13 
 14 @property (weak, nonatomic) IBOutlet UITextField *msgTextField;
 15 @property (strong, nonatomic) IBOutletCollection(UITextView) NSArray *chatTextView;
 16 
 17 @end
 18 
 19 @implementation ViewController
 20 
 21 - (void)viewDidLoad {
 22     [super viewDidLoad];
 23     // Do any additional setup after loading the view, typically from a nib.
 24     [self initSocket];
 25 }
 26 
 27 - (void)initSocket{
 28   //一、建立 Socket
 29     
 30     /*
 31      參數
 32      第一個參數: adress_family,協議簇 AF_INET ---> IPV4(本地主機通信)    IPV6   AF_UNIX(本地主機通信,linux使用)
 33      第二個參數: 數據格式----> SOCK_STREAM(TCP)/SOCK_DGRAM(UDP);TCP基於數據流傳輸,UDP基於數據報文傳輸
 34      第三個參數: protocol  IPPROTO_TCP,若是傳入 0 ,會自動根據第二個參數,選中合適的協議;服務端自動給你確認須要什麼協議
 35      返回值: 成功 -----> 正值   失敗 -------> -1
 36      */
 37     
 38     _clientSocket = socket(AF_INET, SOCK_STREAM, 0);
 39     
 40     //二、鏈接服務器
 41     struct sockaddr_in sAddr = {0};
 42     
 43     sAddr.sin_len = sizeof(sAddr);//長度
 44     
 45     inet_aton(serevr_ip, &sAddr.sin_addr);  //字節序,分爲:主機字節序(整數在主機中存放的順序)和網絡字節序。
 46     
 47     sAddr.sin_port = htons(server_port);
 48     
 49     sAddr.sin_family = AF_INET; //協議簇
 50     
 51     /*
 52      第一個參數: 客戶端 Socket
 53      
 54      第二個參數: 指向數據結構 sockeAddr 的指針,其中包括目的端口和 IP地址
 55      
 56      第三個參數: 結構體數據長度
 57      
 58      返回值:成功 ----> 0  其餘 ----> 錯誤代號
 59      */
 60     int  connectFlag = connect(_clientSocket, (struct sockaddr *)&sAddr, sizeof(sAddr));
 61     
 62     if (connectFlag == 0) {
 63         //開啓線程後要開爲一個長度線程
 64         NSThread *thread = [[NSThread alloc] initWithTarget:self
 65                                                    selector:@selector(receiveAction) object:nil];
 66         [thread start];
 67         
 68     }else{
 69         NSLog(@"鏈接錯誤");
 70         
 71     }
 72 }
 73 
 74 
 75 - (void)receiveAction{
 76     while (1) {
 77         //內容緩存區
 78         char rec_msg[1024] = {0};
 79         
 80         /**
 81          監聽服務端發送的數據
 82 
 83          @param _clientSocket 客戶端Socket
 84          @param rec_msg 發送內容地址,內容緩存區
 85          @param rec_msg 發送內容長度
 86          @param rec_msg 發送方式標識,通常爲 0
 87          @return 成功---> 返回字節數,失敗---->SOCKET-ERROR
 88          */
 89         recv(_clientSocket, rec_msg, sizeof(rec_msg), 0);
 90         printf("----->%s\n",rec_msg);
 91     }
 92 }
 93 
 94 - (void)sendMessage:(NSString *)msg{
 95     const char *send_Message = [msg cStringUsingEncoding:NSUTF8StringEncoding];
 96     send(_clientSocket,send_Message,strlen(send_Message) ,0);
 97 }
 98 
 99 - (IBAction)sendAction:(UIButton *)sender {
100     if ([_msgTextField.text isEqualToString:@""]) {
101         NSLog(@"發送消息不能爲空");
102         return;
103     }
104     [self sendMessage:_msgTextField.text];
105 }
106 
107 - (void)didReceiveMemoryWarning {
108     [super didReceiveMemoryWarning];
109     // Dispose of any resources that can be recreated.
110 }
111 
112 
113 @end
View Code

TCP鏈接之後進行通信可能會發生丟包事件,這時客戶端和服務器端就要進行必定的約定,定義一些 「/n」 之類的一些標識符。linux

打開一個終端端口,輸入:面試

nc -l 6969 //監聽客戶端數據的發送算法

 

而後運行客戶端的程序代碼,不然控制檯會打印:"鏈接錯誤";緩存

在模擬器中輸入:33333服務器

終端也會出現:33333網絡

在終端輸入:-----》》》welcome  即時通信數據結構

在程序的控制檯會打印:socket

終端如圖:ide

 

Socket服務器端代碼atom

代碼圖一:

 

 

代碼圖二:

 

代碼圖三:

 

代碼圖四:

 

代碼圖五:

 

面試題:

Socket 監聽一個端口,最多有多少個鏈接?

與客戶端最多有1024個鏈接,但同時能鏈接的請求最多5個。 

 

服務器同一時刻,一個端口只能創建一個鏈接服務端,可是它會生成一個等待隊列,每個請求它都會放在這個請求隊列裏,根據某一算法在某一時刻處理哪一個請求。

相關文章
相關標籤/搜索