IDEA Maven搭建WebSocket與iOS端的簡單實(shí)現(xiàn)

IDEA Maven搭建WebSocket與iOS端的簡單實(shí)現(xiàn)

本人Java新手钝腺,學(xué)習(xí)過程中嘗試Java與移動(dòng)端的Websocket對(duì)接,如有不對(duì)的地方柔吼,望指正掰邢!

本文主要講WebSocket在Java和iOS部分的實(shí)現(xiàn)牺陶,使用的開發(fā)工具IntelliJ IDEA 和 XCode。

JDK 1.8版本辣之,Maven 3.5.4

基本環(huán)境

使用Maven配置工程相關(guān)依賴庫掰伸,iOS端使用Objective-C,依賴SocketRocket(SRWebSocket)三方庫實(shí)現(xiàn)WebSocket(建議使用CocoaPods導(dǎo)入SocketRocket)怀估,并基于SocketRocket封裝SocketRocketTool工具類狮鸭,可以用少量的代碼實(shí)現(xiàn)Java端和iOS端的WebSocket連接。

本文僅僅實(shí)現(xiàn)了簡單的WebSocket連接多搀,復(fù)雜的功能需要各個(gè)開發(fā)小伙伴根據(jù)業(yè)務(wù)需求自行處理歧蕉。

一、Java部分的實(shí)現(xiàn)

先附上Java版本的代碼地址:GitHub - angletiantang/WebSocket_Java: Java版本的WebSocket Demo

1.創(chuàng)建新工程 Spring Initializr -> Next

1.選擇類型
2.設(shè)置項(xiàng)目名稱
3.配置基本信息
4.創(chuàng)建Maven項(xiàng)目康铭,包含Websocket和MySQL
5.完成創(chuàng)建

2.修改application.yml配置文件

2.1 修改application.properties配置文件惯退,配置application.yml文件。

重命名application.yml文件1
重命名application.yml文件2

2.2 配置application.yml文件

spring:

aop:

? ? auto: true

proxy-target-class: true

datasource:

? ? type: com.zaxxer.hikari.HikariDataSource

driver-class-name: com.mysql.cj.jdbc.Driver

url: jdbc:mysql://您的MySQL配置路徑?zeroDateTimeBehavior=CONVERT_TO_NULL&useUnicode=true&characterEncoding=UTF8&useSSL=false&serverTimezone=GMT&allowPublicKeyRetrieval=true

username: MySql用戶名(一般是root)

password: MySql密碼

hikari:

? ? ? auto-commit: true

minimum-idle: 2

maximum-pool-size: 10

connection-timeout: 10000

max-lifetime: 600000

idle-timeout: 60000

validation-timeout: 1000

leak-detection-threshold: 30000

server:

? port: 8081

logging.level.com.gjh: DEBUG

hystrix:

command:

default:

execution:

isolation:

thread:

? ? ? ? ? ? timeoutInMilliseconds: 60000

sys:

? version: v0.0.1.1

配置application.yml

完成application.yml文件的配置从藤。

2.3 修改pom.xml配置文件

配置pom.xml依賴

pom.xml文件配置:

<dependencies>

? <!--Spring Boot -->

? <!--支持 Web 應(yīng)用開發(fā)催跪,包含 Tomcat 和 spring-mvc锁蠕。 -->

? <dependency>

? <groupId>org.springframework.boot</groupId>

? <artifactId>spring-boot-starter-web</artifactId>

? <version>${spring-boot.version}</version>

? </dependency>

? <dependency>

? <groupId>commons-io</groupId>

? <artifactId>commons-io</artifactId>

? <version>2.4</version>

? </dependency>

? <dependency>

? <groupId>org.springframework.boot</groupId>

? <artifactId>spring-boot-starter-jdbc</artifactId>

? <version>${spring-boot.version}</version>

? </dependency>

? <dependency>

? <groupId>org.springframework.boot</groupId>

? <artifactId>spring-boot-devtools</artifactId>

? <version>${spring-boot.version}</version>

? <optional>true</optional>

? </dependency>

? <dependency>

? <groupId>org.springframework.boot</groupId>

? <artifactId>spring-boot-dependencies</artifactId>

? <version>${spring-boot.version}</version>

? <type>pom</type>

? <scope>import</scope>

? </dependency>

? <dependency>

? <groupId>mysql</groupId>

? <artifactId>mysql-connector-java</artifactId>

? <version>8.0.11</version>

? </dependency>

? <!-- 連接池配置 -->

? <dependency>

? <groupId>com.zaxxer</groupId>

? <artifactId>HikariCP</artifactId>

? <version>2.7.4</version>

? </dependency>

? <dependency>

? <groupId>com.google.code.gson</groupId>

? <artifactId>gson</artifactId>

? <version>2.8.5</version>

? </dependency>

? <dependency>

? <groupId>com.alibaba</groupId>

? <artifactId>fastjson</artifactId>

? <version>1.2.44</version>

? </dependency>

? <dependency>

? <groupId>org.springframework.boot</groupId>

? <artifactId>spring-boot-starter-test</artifactId>

? <version>${spring-boot.version}</version>

? <scope>test</scope>

? </dependency>

? <!--<dependency>-->

? <!--<groupId>com.fasterxml.jackson.core</groupId>-->

? <!--<artifactId>jackson-databind</artifactId>-->

? <!--<version>2.7.4</version>-->

? <!--</dependency>-->

? <dependency>

? <groupId>org.jetbrains</groupId>

? <artifactId>annotations</artifactId>

? <version>RELEASE</version>

? </dependency>

? <dependency>

? <groupId>org.java-websocket</groupId>

? <artifactId>Java-WebSocket</artifactId>

? <version>1.3.0</version>

? </dependency>

? <dependency>

? <groupId>org.springframework.boot</groupId>

? <artifactId>spring-boot-starter-websocket</artifactId>

? <version>${spring-boot.version}</version>

? </dependency>

</dependencies>

完成pom.xml文件的配置。

2.4 Java編碼

在src-main-java-com.你的項(xiàng)目 路徑下創(chuàng)建package

創(chuàng)建package
創(chuàng)建相關(guān)文件

創(chuàng)建GetHttpSessionConfigurator.java懊蒸,RequestListener.java 荣倾,WebSocketConfig.java,WebSocketController.java四個(gè)java文件骑丸,用來實(shí)現(xiàn)Websocket舌仍。

其中GetHttpSessionConfigurator.java用來獲取httpSession,繼承于Configurator

package com.websocket.demo.config;

import javax.servlet.http.HttpSession;
import javax.websocket.HandshakeResponse;
import javax.websocket.server.HandshakeRequest;
import javax.websocket.server.ServerEndpointConfig;
import javax.websocket.server.ServerEndpointConfig.Configurator;

public class GetHttpSessionConfigurator extends Configurator
{
??? public void modifyHandshake(ServerEndpointConfig config, HandshakeRequest request, HandshakeResponse response) {
??????? HttpSession httpSession = (HttpSession) request.getHttpSession();
??????? if(httpSession != null){
??????????? config.getUserProperties().put(HttpSession.class.getName(), httpSession);
??????? }
??? }
}

GetHttpSessionConfigurator.java

使用方法java WebSocket之獲取HttpSession通危,登錄用戶的所有信息-博客-最代碼

RequestListener.java 中的代碼部分

package com.websocket.demo.config;

import javax.servlet.ServletRequestEvent;

import javax.servlet.ServletRequestListener;

import javax.servlet.annotation.WebListener;

import javax.servlet.http.HttpServletRequest;

import org.springframework.stereotype.Component;

@WebListener//配置Listener

@Component

public class RequestListener implements ServletRequestListener

{

? ? public void requestInitialized(ServletRequestEvent sre)

? ? {

? ? ? ? //將所有request請求都攜帶上httpSession

? ? ? ? ((HttpServletRequest) sre.getServletRequest()).getSession();

? ? }

? ? public RequestListener()

? ? {

? ? }

? ? public void requestDestroyed(ServletRequestEvent arg0)

? ? {

? ? }

}

RequestListener.java

WebSocketConfig.java 代碼

package com.websocket.demo.config;

import org.springframework.context.annotation.Bean;

import org.springframework.context.annotation.Configuration;

import org.springframework.web.socket.server.standard.ServerEndpointExporter;

@Configuration

public class WebSocketConfig {

? ? @Bean

? ? public ServerEndpointExporter serverEndpointExporter() {

? ? ? ? return new ServerEndpointExporter();

? ? }

}

WebSocketConfig.java

WebSocketController.java 關(guān)鍵部分代碼

建立成功
連接關(guān)閉
收到消息
發(fā)生錯(cuò)誤
發(fā)送消息

Java端代碼到這里救基本OK了铸豁,點(diǎn)擊Debug運(yùn)行,出現(xiàn)下面的效果證明運(yùn)行OK黄鳍。

啟動(dòng)運(yùn)行OK

二推姻、iOS部分的實(shí)現(xiàn)

附iOS OC版本的代碼地址:GitHub - angletiantang/WebSocket_OC: OC版本的WebSocket Demo,基于SocketRocket實(shí)現(xiàn),上層進(jìn)行簡單的封裝

1.創(chuàng)建iOS工程

創(chuàng)建新工程1
創(chuàng)建新工程2
創(chuàng)建新工程3

推薦使用CocoaPods集成SocketRocket三方庫,如果不想使用可以直接把SocketRocket源碼拖入工程框沟。

搜索SocketRocket
搜索結(jié)果
創(chuàng)建和編輯Podfile文件
編輯Podfile文件
pod install安裝
導(dǎo)入SocketRocket完成

之后使用.xcworkspace文件打開工程。

2.實(shí)現(xiàn)代碼部分

導(dǎo)入SocketRocketTool.h和SocketRocketTool.m文件增炭。

2.1 SocketRocketTool代碼使用

使用SocketRocketTool忍燥,第一步引入頭文件。

引入頭文件

第二步設(shè)置實(shí)現(xiàn)代理方法隙姿。

設(shè)置代理
實(shí)現(xiàn)代理方法


2.1 SocketRocketTool代碼實(shí)現(xiàn)

SocketRocketTool.h 中的代碼

#import <Foundation/Foundation.h>

#import <SocketRocket.h>

@protocol SocketRocketToolDelegate <NSObject>

@optional

// 收到id類型消息的回調(diào)

- (void)webSocket:(SRWebSocket *_Nullable)webSocket didReceiveMessage:(id _Nullable )message;

// 收到j(luò)son string類型消息的回調(diào)

- (void)webSocket:(SRWebSocket *_Nullable)webSocket didReceiveMessageWithString:(NSString *_Nullable)string;

// 收到data類型消息的回調(diào)

- (void)webSocket:(SRWebSocket *_Nullable)webSocket didReceiveMessageWithData:(NSData *_Nullable)data;

// 收到連接錯(cuò)誤的回調(diào)

- (void)webSocket:(SRWebSocket *_Nullable)webSocket didFailWithError:(NSError *_Nullable)error;

// 收到連接關(guān)閉的回調(diào)

- (void)webSocket:(SRWebSocket *_Nullable)webSocket didCloseWithCode:(NSInteger)code reason:(nullable NSString *)reason wasClean:(BOOL)wasClean;

// 收到Ping-Pong的回調(diào)

- (void)webSocket:(SRWebSocket *_Nullable)webSocket didReceivePingWithData:(nullable NSData *)data;

- (void)webSocket:(SRWebSocket *_Nullable)webSocket didReceivePong:(nullable NSData *)pongData;

//

- (BOOL)webSocketShouldConvertTextFrameToString:(SRWebSocket *_Nullable)webSocket NS_SWIFT_NAME(webSocketShouldConvertTextFrameToString(_:));

// webSocket已經(jīng)打開

- (void)webSocketDidOpen:(SRWebSocket *_Nullable)webSocket;

// webSocket已經(jīng)關(guān)閉

- (void)webSocketDidClose:(SRWebSocket *_Nullable)webSocket;

@end;

@interface SocketRocketTool : NSObject

// 代理屬性

@property(nonatomic,weak) id<SocketRocketToolDelegate> delegate;

// 觀察隊(duì)列

@property (nonatomic,strong) NSMutableSet *observerQueue;

//

@property (nonatomic,strong) NSString *wsURLString;

// 單例對(duì)象

+ (instancetype)sharedInstance;

// 連接webSocket

- (void)connect;

// 重連webSocket

- (void)reconnect;

// 關(guān)閉WebSocket的連接

- (void)closeWebSocket;

// 添加觀察

- (void)socketAddObserver:(id _Nullable )observer;

// 移除觀察

- (void)socketRemoveObserver:(id _Nullable )observer;

// 發(fā)送json數(shù)據(jù)

- (BOOL)sendString:(NSString *)string error:(NSError **)error;

// 發(fā)送data

- (BOOL)sendData:(nullable NSData *)data error:(NSError **)error;

@end


SocketRocketTool.m 中的代碼

#import "SocketRocketTool.h"

// 接受SRWebSocketDelegate

@interface SocketRocketTool()<SRWebSocketDelegate>

// SRWebSocket

@property (nonatomic,strong)SRWebSocket *socket;

// 發(fā)送ping的計(jì)時(shí)器

@property(nonatomic,strong)NSTimer *pingTimer;

// 重新連接的計(jì)時(shí)器

@property(nonatomic,strong)NSTimer *reconnetTimer;

@end

static const NSTimeInterval WebSocketHeartBeatTimeInterval = 1.0;

@implementation SocketRocketTool

// 單例方法

static SocketRocketTool * instance = nil;

+ (instancetype)sharedInstance

{

? ? static dispatch_once_t onceToken ;

? ? dispatch_once(&onceToken, ^{

? ? ? ? instance = [[super allocWithZone:NULL] init];

? ? }) ;

? ? return instance ;

}

+ (id)allocWithZone:(struct _NSZone *)zone

{

? ? return [SocketRocketTool sharedInstance];

}

- (id)copyWithZone:(struct _NSZone *)zone

{

? ? return [SocketRocketTool sharedInstance];

}

#pragma mark SRWebSocket? Open&Close&Send

// 連接webSocket

- (void)connect

{

? ? // 發(fā)出連接webSocket的通知,需不需要使用由自己決定

//? ? NSNotification *notification = [[NSNotification alloc]initWithName:kWebSocketWillConnectNoti object:nil userInfo:nil];

//? ? [[NSNotificationCenter defaultCenter]postNotification:notification];

? ? if (![self isNullObject:self.socket])

? ? {

? ? ? ? [self.socket close];

? ? ? ? self.socket = nil;

? ? }


? ? self.socket = [[SRWebSocket alloc] initWithURLRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:self.wsURLString]]];

? ? self.observerQueue=[[NSMutableSet alloc] init];

? ? self.socket.delegate=self;

? ? [self.socket open];

? ? NSLog(@"[方法:%s-行數(shù):%d]WebSocket_Host_URL:%@",__FUNCTION__,__LINE__,self.wsURLString);

}

-(void)socketAddObserver:(id)observer{

? ? if (![self.observerQueue containsObject:observer]) {

? ? ? ? [self.observerQueue addObject:observer];

? ? }

}

-(void)socketRemoveObserver:(id)observer{

? ? if ([self.observerQueue containsObject:observer]) {

? ? ? ? [self.observerQueue removeObject:observer];

? ? }

}

// 發(fā)送消息的方法

- (BOOL)sendString:(NSString *)string error:(NSError **)error{

? ? // webSocket沒有打開的狀態(tài)下

? ? if (self.socket.readyState != SR_OPEN) {

? ? ? ? if (self.delegate&&[self.delegate respondsToSelector:@selector(webSocketDidClose:)]) {

? ? ? ? ? ? [self.delegate webSocketDidClose:self.socket];

? ? ? ? }

? ? ? ? NSLog(@"發(fā)送json時(shí)webSocket沒有打開!");

? ? ? ? return NO;

? ? }

? ? if ([self stringIsNull:string]) {

? ? ? ? NSLog(@"[方法:%s-行數(shù):%d]發(fā)送json數(shù)據(jù)為空!",__FUNCTION__,__LINE__);

? ? ? ? return NO;

? ? }

? ? NSLog(@"\n[方法:%s-行數(shù):%d]\n發(fā)送消息:\n%@\n",__FUNCTION__,__LINE__,string);

? ? [self.socket send:string];

? ? return YES;

}

- (BOOL)sendData:(nullable NSData *)data error:(NSError **)error{

? ? if (self.socket.readyState != SR_OPEN) {

? ? ? ? if (self.delegate && [self.delegate respondsToSelector:@selector(webSocketDidClose:)]) {

? ? ? ? ? ? [self.delegate webSocketDidClose:self.socket];

? ? ? ? }

? ? ? ? NSLog(@"發(fā)送data時(shí)webSocket沒有打開!");

? ? ? ? return NO;

? ? }

? ? if (data.length==0) {

? ? ? ? NSLog(@"[方法:%s-行數(shù):%d]發(fā)送data數(shù)據(jù)為空!",__FUNCTION__,__LINE__);

? ? ? ? return NO;

? ? }

? ? [self.socket send:data ];

? ? return YES;

}

#pragma mark - SRWebSocketDelegate

- (void)webSocket:(SRWebSocket *)webSocket didReceiveMessage:(id)message

{

? ? NSString * aMessage = (NSString*)message?:@"";

? ? if (![self stringIsNull:aMessage])

? ? {

? ? ? ? NSDictionary *dic = @{@"message":aMessage};

? ? ? ? NSLog(@"webSocket根源收到的消息:%@",dic);

//? ? ? ? NSNotification *notification = [[NSNotification alloc]initWithName:kWebSocketReciveMessgeNoti object:nil userInfo:dic];

//? ? ? ? [[NSNotificationCenter defaultCenter]postNotification:notification];

? ? }else

? ? {

? ? ? ? NSLog(@"[方法:%s-行數(shù):%d] message is null !",__FUNCTION__,__LINE__);

? ? }


? ? if (self.delegate&&[self.delegate respondsToSelector:@selector(webSocket:didReceiveMessage:)]) {

? ? ? ? [self.delegate webSocket:webSocket didReceiveMessage:message];

? ? }

}

- (void)webSocket:(SRWebSocket *)webSocket didReceiveMessageWithString:(NSString *)string{

? ? if (self.delegate&&[self.delegate respondsToSelector:@selector(webSocket:didReceiveMessageWithString:)]) {

? ? ? ? [self.delegate webSocket:webSocket didReceiveMessageWithString:string];

? ? }

}

- (void)webSocket:(SRWebSocket *)webSocket didReceiveMessageWithData:(NSData *)data{

? ? if (self.delegate&&[self.delegate respondsToSelector:@selector(webSocket:didReceiveMessageWithData:)]) {

? ? ? ? [self.delegate webSocket:webSocket didReceiveMessageWithData:data];

? ? }

}

- (void)webSocketDidOpen:(SRWebSocket *)webSocket{

? ? NSLog(@"[方法:%s-行數(shù):%d]\nwebSocketDidOpen!\n",__FUNCTION__,__LINE__);

? ? // 連接webSocket成功時(shí)發(fā)出的通知

//? ? NSNotification *notification = [[NSNotification alloc]initWithName: kWebSocketConnectDidSuccessNoti object:nil userInfo:nil];

//? ? [[NSNotificationCenter defaultCenter]postNotification:notification];

? ? // webSockeet連接每一秒發(fā)送一個(gè)Ping指令

? ? [self startPing];


//? ? NSDictionary * testDic = @{@"key1":@"value1",@"key2":@"value2"};

//? ? NSString * dicString = [DictionaryToJsonTool dictionaryToJSONString:testDic];

? ? NSError *error;

? ? [self sendString:@"testString" error:&error];


? ? if (self.delegate&&[self.delegate respondsToSelector:@selector(webSocketDidOpen:)]) {

? ? ? ? [self.delegate webSocketDidOpen:webSocket];

? ? }

}

- (void)webSocket:(SRWebSocket *)webSocket didFailWithError:(NSError *)error{

? ? NSLog(@"[方法:%s-行數(shù):%d] [webSocket connect fail error resson:]%@\n[closed createTime]%@[closed host]%@\n",__FUNCTION__, __LINE__,error.description,[NSDate date],webSocket.url);

? ? if (self.delegate&&[self.delegate respondsToSelector:@selector(webSocket:didFailWithError:)]) {

? ? ? ? [self.delegate webSocket:webSocket didFailWithError:error];

? ? }

}

- (void)webSocket:(SRWebSocket *)webSocket didCloseWithCode:(NSInteger)code reason:(nullable NSString *)reason wasClean:(BOOL)wasClean{

? ? NSLog(@"[方法:%s-行數(shù):%d][webSocketClosed with reason:]%@\n[closed createTime:]%@\n[closed host:]%@\n" ,__FUNCTION__, __LINE__,reason,[NSDate date],webSocket.url);

? ? if (self.delegate&&[self.delegate respondsToSelector:@selector(webSocket:didCloseWithCode:reason:wasClean:)]) {

? ? ? ? [self.delegate webSocket:webSocket didCloseWithCode:code reason:reason wasClean:wasClean];

? ? }

? ? // webSocket斷開連接發(fā)出的通知

//? ? NSNotification *notification = [[NSNotification alloc]initWithName: kWebSocketConnectDidCloseNoti object:nil userInfo:nil];

//? ? [[NSNotificationCenter defaultCenter]postNotification:notification];

}

- (void)webSocket:(SRWebSocket *)webSocket didReceivePingWithData:(nullable NSData *)data{

? ? if (self.delegate&&[self.delegate respondsToSelector:@selector(webSocket:didReceivePingWithData:)]) {

? ? ? ? [self.delegate webSocket:webSocket didReceivePingWithData:data];

? ? }

}

- (void)webSocket:(SRWebSocket *)webSocket didReceivePong:(nullable NSData *)pongData{

? ? if (self.delegate&&[self.delegate respondsToSelector:@selector(webSocket:didReceivePong:)]) {

? ? ? ? [self.delegate webSocket:webSocket didReceivePong:pongData];

? ? }

}

#pragma -mark Heartbeat

-(void)startPing{

? ? if (_pingTimer) {

? ? ? ? [_pingTimer invalidate];

? ? ? ? _pingTimer = nil;

? ? }


? ? if (_reconnetTimer) {

? ? ? ? [_reconnetTimer invalidate];

? ? ? ? _reconnetTimer = nil;

? ? }

? ? _pingTimer = [NSTimer scheduledTimerWithTimeInterval:WebSocketHeartBeatTimeInterval target:self selector:@selector(sendPing:) userInfo:nil repeats:YES];

? ? [[NSRunLoop currentRunLoop] addTimer:_pingTimer forMode:NSRunLoopCommonModes];

}

-(void)sendPing:(id)sender{

? ? if (self.socket.readyState == SR_OPEN)

? ? {

? ? ? ? NSError *error;

? ? ? ? [self.socket sendPing:nil];

? ? ? ? if (error) {

? ? ? ? ? ? NSLog(@"%s:%d %@", __FUNCTION__, __LINE__,error);

? ? ? ? }

? ? }else

? ? {

? ? ? ? [_pingTimer invalidate];

? ? ? ? _pingTimer = nil;

? ? ? ? [self reconnect];

? ? }

}

- (void)destoryHeartBeat{

? ? if (_pingTimer) {

? ? ? ? [_pingTimer invalidate];

? ? ? ? _pingTimer = nil;

? ? }

}

#pragma -mark Reconnect

-(void)reconnect{

? ? // 連接

? ? [self connect];

? ? NSLog(@"[%s:%d]reconnecting! ",__FUNCTION__,__LINE__);

? ? [self closeWebSocket];

? ? _reconnetTimer = [NSTimer scheduledTimerWithTimeInterval:5.0 target:self selector:@selector(startReconnect) userInfo:nil repeats:YES];

? ? [[NSRunLoop currentRunLoop] addTimer:_reconnetTimer forMode:NSRunLoopCommonModes];

}

-(void)startReconnect

{

? ? self.socket = nil;

? ? [self connect];

? ? NSLog(@"%s:%d socket reconnecting!", __FUNCTION__, __LINE__);

}

-(void)closeWebSocket{

? ? if (self.socket){

? ? ? ? [self.socket close];

? ? ? ? self.socket = nil;

? ? ? ? [self destoryHeartBeat];

? ? }

}

#pragma -mark util

- (BOOL)stringIsNull:(NSString *)string

{

? ? if (![string isKindOfClass:[NSString class]]) {

? ? ? ? return YES;

? ? }


? ? if (!string || [string isKindOfClass:[NSNull class]] || string.length == 0 || [string isEqualToString:@""]) {

? ? ? ? return YES;

? ? }else{

? ? ? ? return NO;

? ? }

}

- (BOOL)isNullObject:(id)anObject

{

? ? if (!anObject || [anObject isKindOfClass:[NSNull class]]) {

? ? ? ? return YES;

? ? }else{

? ? ? ? return NO;

? ? }

}

@end


三梅垄、運(yùn)行工程

注意需要保證電腦連接 和 手機(jī)連接在同一個(gè)局域網(wǎng)之內(nèi)。

然后運(yùn)行工程输玷,Websocket成功建立連接队丝。

XCode打印
IDEA打印

至此,Java端和iOS移動(dòng)端的Websocket已經(jīng)成功建立連接欲鹏。

如果有不對(duì)的地方希望大家指出机久!

聯(lián)系方式:

QQ:871810101

郵箱:871810101@qq.com

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市赔嚎,隨后出現(xiàn)的幾起案子膘盖,更是在濱河造成了極大的恐慌,老刑警劉巖尤误,帶你破解...
    沈念sama閱讀 210,914評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件侠畔,死亡現(xiàn)場離奇詭異,居然都是意外死亡损晤,警方通過查閱死者的電腦和手機(jī)软棺,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,935評(píng)論 2 383
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來尤勋,“玉大人喘落,你說我怎么就攤上這事茵宪。” “怎么了揖盘?”我有些...
    開封第一講書人閱讀 156,531評(píng)論 0 345
  • 文/不壞的土叔 我叫張陵眉厨,是天一觀的道長。 經(jīng)常有香客問我兽狭,道長憾股,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,309評(píng)論 1 282
  • 正文 為了忘掉前任箕慧,我火速辦了婚禮服球,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘颠焦。我一直安慰自己斩熊,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,381評(píng)論 5 384
  • 文/花漫 我一把揭開白布伐庭。 她就那樣靜靜地躺著粉渠,像睡著了一般。 火紅的嫁衣襯著肌膚如雪圾另。 梳的紋絲不亂的頭發(fā)上霸株,一...
    開封第一講書人閱讀 49,730評(píng)論 1 289
  • 那天,我揣著相機(jī)與錄音集乔,去河邊找鬼去件。 笑死,一個(gè)胖子當(dāng)著我的面吹牛扰路,可吹牛的內(nèi)容都是我干的尤溜。 我是一名探鬼主播,決...
    沈念sama閱讀 38,882評(píng)論 3 404
  • 文/蒼蘭香墨 我猛地睜開眼汗唱,長吁一口氣:“原來是場噩夢啊……” “哼宫莱!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起渡嚣,我...
    開封第一講書人閱讀 37,643評(píng)論 0 266
  • 序言:老撾萬榮一對(duì)情侶失蹤梢睛,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后识椰,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體绝葡,經(jīng)...
    沈念sama閱讀 44,095評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,448評(píng)論 2 325
  • 正文 我和宋清朗相戀三年腹鹉,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了藏畅。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,566評(píng)論 1 339
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖愉阎,靈堂內(nèi)的尸體忽然破棺而出绞蹦,到底是詐尸還是另有隱情,我是刑警寧澤榜旦,帶...
    沈念sama閱讀 34,253評(píng)論 4 328
  • 正文 年R本政府宣布幽七,位于F島的核電站,受9級(jí)特大地震影響溅呢,放射性物質(zhì)發(fā)生泄漏澡屡。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,829評(píng)論 3 312
  • 文/蒙蒙 一咐旧、第九天 我趴在偏房一處隱蔽的房頂上張望驶鹉。 院中可真熱鬧,春花似錦铣墨、人聲如沸室埋。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,715評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽姚淆。三九已至,卻和暖如春屡律,著一層夾襖步出監(jiān)牢的瞬間肉盹,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,945評(píng)論 1 264
  • 我被黑心中介騙來泰國打工疹尾, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人骤肛。 一個(gè)月前我還...
    沈念sama閱讀 46,248評(píng)論 2 360
  • 正文 我出身青樓纳本,卻偏偏與公主長得像,于是被迫代替她去往敵國和親腋颠。 傳聞我的和親對(duì)象是個(gè)殘疾皇子繁成,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,440評(píng)論 2 348

推薦閱讀更多精彩內(nèi)容