即时通讯(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   //1、创建 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     //2、连接服务器
 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
",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” 之类的一些标识符。

打开一个终端端口,输入:

nc -l 6969 //监听客户端数据的发送

然后运行客户端的程序代码,否则控制台会打印:"连接错误";

在模拟器中输入:33333

终端也会出现:33333

在终端输入:-----》》》welcome  即时通讯

在程序的控制台会打印:

终端如图:

Socket服务器端代码

代码图一:

 

代码图二:

代码图三:

代码图四:

代码图五:

面试题:

Socket 监听一个端口,最多有多少个连接?

与客户端最多有1024个连接,但同时能连接的请求最多5个。 

服务器同一时刻,一个端口只能建立一个连接服务端,但是它会生成一个等待队列,每一个请求它都会放在这个请求队列里,根据某一算法在某一时刻处理哪个请求。

原文地址:https://www.cnblogs.com/EchoHG/p/9191860.html