即时通讯(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\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
TCP连接以后进行通讯可能会发生丢包事件,这时客户端和服务器端就要进行一定的约定,定义一些 “/n” 之类的一些标识符。
打开一个终端端口,输入:
nc -l 6969 //监听客户端数据的发送
然后运行客户端的程序代码,否则控制台会打印:"连接错误";
在模拟器中输入:33333
终端也会出现:33333
在终端输入:-----》》》welcome 即时通讯
在程序的控制台会打印:
终端如图:
Socket服务器端代码
代码图一:
代码图二:
代码图三:
代码图四:
代码图五:
面试题:
Socket 监听一个端口,最多有多少个连接?
与客户端最多有1024个连接,但同时能连接的请求最多5个。
服务器同一时刻,一个端口只能建立一个连接服务端,但是它会生成一个等待队列,每一个请求它都会放在这个请求队列里,根据某一算法在某一时刻处理哪个请求。