ios仿微信的demo

10月19日闲的蛋疼,做了个
仿微信的聊天工具
git地址:[url]https://github.com/killinux/mysocket/tree/master/websocket/project/Test[/url]
ui参考的网上例子http://ios.9tech.cn/news/2013/1111/38520.html
服务端用 tomcat7的websocket
客户端
1.可以用浏览器
2.sockroket的ios客户端,ios8,开发工具xcode6
ios客户端代码如下代码:
ViewController.m

//
// ViewController.m
// BubbleDemo
//
// Created by xiao7 on 14/10/19.
// Copyright (c) 2014年 killinux. All rights reserved.
//

#import "ViewController.h"

@interface ViewController ()

@end

@implementation ViewController

NSString *websocket_url = @"ws://192.168.0.102:8080/webs/websocket/test";
NSString *myName = @"haoning";
NSString *toName = @"all";
- (void)viewDidLoad {
[super viewDidLoad];
//----init data---begin----
// NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys:@"weixin",@"name",@"这是一个测试",@"content", nil];
// NSDictionary *dict1 = [NSDictionary dictionaryWithObjectsAndKeys:@"haoning",@"name",@"hello",@"content", nil];
// NSDictionary *dict7 = [NSDictionary dictionaryWithObjectsAndKeys:@"weixin",@"name",@",长数据测试。",@"content", nil];
// _resultArray = [NSMutableArray arrayWithObjects:dict,dict1, nil];
// [_resultArray addObject:dict7];

_resultArray = [[NSMutableArray alloc] init];
//----init data---end----
//websocket---begin---
_mywebSocket.delegate = nil;
[_mywebSocket close];
_mywebSocket = [[SRWebSocket alloc] initWithURLRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:websocket_url]]];
_mywebSocket.delegate = self;
[_mywebSocket open];
NSLog(@"open success!");
//websocket---end----
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
//pragma websocket
- (void)webSocketDidOpen:(SRWebSocket *)webSocket;
{
NSLog(@"Websocket Connected");
self.title = @"Connected!";
}

- (void)webSocket:(SRWebSocket *)webSocket didFailWithError:(NSError *)error;
{
NSLog(@":( Websocket Failed With Error %@", error);
_mywebSocket = nil;
}

- (void)webSocket:(SRWebSocket *)webSocket didReceiveMessage:(id)message;
{
NSLog(@"websocket Received \"%@\"", message);
NSArray *messageArray = [message componentsSeparatedByString:@","];
if(messageArray.count<3){
NSLog(@"error parameter not right:%@",message);
// NSDictionary *dict8 = [NSDictionary dictionaryWithObjectsAndKeys:@"haoning",@"name",message,@"content", nil];
// [_resultArray addObject:dict8];
}else{
NSDictionary *dict8 = [NSDictionary dictionaryWithObjectsAndKeys:messageArray[0],@"name",messageArray[2],@"content", nil];
[_resultArray addObject:dict8];
}
[tableViewList reloadData];
}

- (void)webSocket:(SRWebSocket *)webSocket didCloseWithCode:(NSInteger)code reason:(NSString *)reason wasClean:(BOOL)wasClean;
{
NSLog(@"WebSocket closed");
self.title = @"Connection Closed! (see logs)";
_mywebSocket = nil;
}
//发送消息
- (IBAction)sendBubbleMessage:(id)sender {
NSString *thistext = messageTxt.text;
NSLog(@"sendBubbleMessage:%@",thistext);
// NSDictionary *dict8 = [NSDictionary dictionaryWithObjectsAndKeys:@"haoning",@"name",thistext,@"content", nil];
// [_resultArray addObject:dict8];
// [tableViewList reloadData];
NSString *sendMessage =[myName stringByAppendingFormat:@",%@,%@",toName,thistext];
[_mywebSocket send:sendMessage];
messageTxt.text=nil;
}

//泡泡文本
- (UIView *)bubbleView:(NSString *)text from:(BOOL)fromSelf withPosition:(int)position{

//计算大小
UIFont *font = [UIFont systemFontOfSize:14];
CGSize size = [text sizeWithFont:font constrainedToSize:CGSizeMake(180.0f, 20000.0f) lineBreakMode:NSLineBreakByWordWrapping];

// build single chat bubble cell with given text
UIView *returnView = [[UIView alloc] initWithFrame:CGRectZero];
returnView.backgroundColor = [UIColor clearColor];

//背影图片
UIImage *bubble = [UIImage imageWithContentsOfFile:[[NSBundle mainBundle] pathForResource:fromSelf?@"SenderAppNodeBkg_HL":@"ReceiverTextNodeBkg" ofType:@"png"]];

UIImageView *bubbleImageView = [[UIImageView alloc] initWithImage:[bubble stretchableImageWithLeftCapWidth:floorf(bubble.size.width/2) topCapHeight:floorf(bubble.size.height/2)]];
//NSLog(@"%f,%f",size.width,size.height);
UILabel *bubbleText = [[UILabel alloc] initWithFrame:CGRectMake(fromSelf?15.0f:22.0f, 20.0f, size.width+10, size.height+10)];
bubbleText.backgroundColor = [UIColor clearColor];
bubbleText.font = font;
bubbleText.numberOfLines = 0;
bubbleText.lineBreakMode = NSLineBreakByWordWrapping;
bubbleText.text = text;
bubbleImageView.frame = CGRectMake(0.0f, 14.0f, bubbleText.frame.size.width+30.0f, bubbleText.frame.size.height+20.0f);
if(fromSelf)
returnView.frame = CGRectMake(320-position-(bubbleText.frame.size.width+30.0f), 0.0f, bubbleText.frame.size.width+30.0f, bubbleText.frame.size.height+30.0f);
else
returnView.frame = CGRectMake(position, 0.0f, bubbleText.frame.size.width+30.0f, bubbleText.frame.size.height+30.0f);

[returnView addSubview:bubbleImageView];
[returnView addSubview:bubbleText];

return returnView;
}

//泡泡语音
- (UIView *)yuyinView:(NSInteger)logntime from:(BOOL)fromSelf withIndexRow:(NSInteger)indexRow withPosition:(int)position{

//根据语音长度
int yuyinwidth = 66+fromSelf;

UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
button.tag = indexRow;
if(fromSelf)
button.frame =CGRectMake(320-position-yuyinwidth, 10, yuyinwidth, 54);
else
button.frame =CGRectMake(position, 10, yuyinwidth, 54);

//image偏移量
UIEdgeInsets imageInsert;
imageInsert.top = -10;
imageInsert.left = fromSelf?button.frame.size.width/3:-button.frame.size.width/3;
button.imageEdgeInsets = imageInsert;

[button setImage:[UIImage imageNamed:fromSelf?@"SenderVoiceNodePlaying":@"ReceiverVoiceNodePlaying"] forState:UIControlStateNormal];
UIImage *backgroundImage = [UIImage imageNamed:fromSelf?@"SenderVoiceNodeDownloading":@"ReceiverVoiceNodeDownloading"];
backgroundImage = [backgroundImage stretchableImageWithLeftCapWidth:20 topCapHeight:0];
[button setBackgroundImage:backgroundImage forState:UIControlStateNormal];

UILabel *label = [[UILabel alloc]initWithFrame:CGRectMake(fromSelf?-30:button.frame.size.width, 0, 30, button.frame.size.height)];
label.text = [NSString stringWithFormat:@"%d''",logntime];
label.textColor = [UIColor grayColor];
label.font = [UIFont systemFontOfSize:13];
label.textAlignment = NSTextAlignmentCenter;
label.backgroundColor = [UIColor clearColor];
[button addSubview:label];

return button;
}

#pragma UITableView

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}

-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return _resultArray.count;
}

-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSDictionary *dict = [_resultArray objectAtIndex:indexPath.row];
UIFont *font = [UIFont systemFontOfSize:14];
CGSize size = [[dict objectForKey:@"content"] sizeWithFont:font constrainedToSize:CGSizeMake(180.0f, 20000.0f) lineBreakMode:NSLineBreakByWordWrapping];

return size.height+44;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{

static NSString *CellIdentifier = @"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
}else{
for (UIView *cellView in cell.subviews){
[cellView removeFromSuperview];
}
}
NSDictionary *dict = [_resultArray objectAtIndex:indexPath.row];

//创建头像
UIImageView *photo ;
if ([[dict objectForKey:@"name"]isEqualToString:@"haoning"]) {
photo = [[UIImageView alloc]initWithFrame:CGRectMake(320-60, 10, 50, 50)];
[cell addSubview:photo];
photo.image = [UIImage imageNamed:@"photo1"];

if ([[dict objectForKey:@"content"] isEqualToString:@"0"]) {
[cell addSubview:[self yuyinView:1 from:YES withIndexRow:indexPath.row withPosition:65]];

}else{
[cell addSubview:[self bubbleView:[dict objectForKey:@"content"] from:YES withPosition:65]];
}

}else{
photo = [[UIImageView alloc]initWithFrame:CGRectMake(10, 10, 50, 50)];
[cell addSubview:photo];
photo.image = [UIImage imageNamed:@"photo"];

if ([[dict objectForKey:@"content"] isEqualToString:@"0"]) {
[cell addSubview:[self yuyinView:1 from:NO withIndexRow:indexPath.row withPosition:65]];
}else{
[cell addSubview:[self bubbleView:[dict objectForKey:@"content"] from:NO withPosition:65]];
}
}

return cell;

}

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{

}

@end



ViewController.h

//
// ViewController.h
// BubbleDemo
//
// Created by xiao7 on 14/10/19.
// Copyright (c) 2014年 killinux. All rights reserved.
//

#import <UIKit/UIKit.h>
#import "SocketRocket/SRWebSocket.h"
@interface ViewController : UIViewController<SRWebSocketDelegate>
{

IBOutlet UITableView *tableViewList;
IBOutlet UITextField *messageTxt;

}
@property (nonatomic, strong) NSMutableArray *resultArray;
@property (nonatomic, strong) SRWebSocket *mywebSocket;
@end

[img]http://dl2.iteye.com/upload/attachment/0102/1799/a98e13ff-9ba8-3328-8b7f-0228835b7f55.png[/img]
演示
chrome上
[img]http://dl2.iteye.com/upload/attachment/0102/1801/febdd1cf-8511-3df9-86f2-4ff25c499010.png[/img]
ios8系统上
[img]http://dl2.iteye.com/upload/attachment/0102/1804/24fbb834-6277-3f56-a4d9-066176eaca0d.png[/img]

html的客户端

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Insert title here</title>
</head>
<script type="text/javascript">
String.prototype.startWith=function(s){
if(s==null||s==""||this.length==0||s.length>this.length)
return false;
if(this.substr(0,s.length)==s)
return true;
else
return false;
return true;
}
Date.prototype.format = function(format) {
var o = {
"M+" : this.getMonth() + 1, //month
"d+" : this.getDate(), //day
"h+" : this.getHours(), //hour
"m+" : this.getMinutes(), //minute
"s+" : this.getSeconds(), //second
"q+" : Math.floor((this.getMonth() + 3) / 3), //quarter
"S" : this.getMilliseconds()
}
if (/(y+)/.test(format))
format = format.replace(RegExp.$1, (this.getFullYear() + "")
.substr(4 - RegExp.$1.length));
for ( var k in o)
if (new RegExp("(" + k + ")").test(format))
format = format.replace(RegExp.$1, RegExp.$1.length == 1 ? o[k]
: ("00" + o[k]).substr(("" + o[k]).length));
return format;
}
var ws = null;
function log(text) {
/* document.getElementById("log").innerHTML = (new Date).getTime() + ": "
+ text + "<br>" + document.getElementById("log").innerHTML; */
document.getElementById("log").innerHTML = new Date().format('yyyy-MM-dd hh:mm:ss') + ","
+ text + "<br>" + document.getElementById("log").innerHTML;
}
function enterSend(){
if(event.keyCode == 13){
document.getElementById("sendbtn").click();
}
}
function startServer() {

var url = document.getElementById("serverip").value;// "ws://192.168.0.102:8887";
if ('WebSocket' in window) {
ws = new WebSocket(url);
} else if ('MozWebSocket' in window) {
ws = new MozWebSocket(url);
} else {
log('浏览器不支持');
return;
}
ws.onopen = function() {
log('唷嘻,连上了');
};
// 收到服务器发送的文本消息, event.data表示文本内容
ws.onmessage = function(event) {
var thisdata = event.data;
if(thisdata.startWith("open")){
//alert(thisdata);
document.getElementById("username").value=thisdata.split(" ")[1];
}else{
//log(event.data);
var showData=event.data.split(",");
log(showData[0]+"说:"+showData[2]);
}
};
ws.onclose = function() {
log('Closed! 刷新页面尝试连接.');
}
//document.getElementById("conbtn").disabled = "true";
//document.getElementById("stopbtn").removeAttribute('disabled');
}
function sendMessage() {
var textMessage = document.getElementById("textMessage").value;
var username = document.getElementById("username").value;
var toUser = "";
if (ws != null && textMessage != "") {
ws.send(username+","+toUser+","+textMessage);
}
document.getElementById("textMessage").value="";
}
function stopconn() {
ws.close();
//document.getElementById("conbtn").removeAttribute('disabled');
//document.getElementById("stopbtn").disabled = "true";
}
</script>
<body onload="startServer()">

<input id="serverip" type="text" size="20"
value="ws://192.168.0.102:8080/webs/websocket/test" />
<!-- ws://192.168.0.102:8887 182.254.155.153 -->
<!-- <input id="conbtn" type="button" onclick="startServer()" value="open" />
<input id="stopbtn" type="button" onclick="stopconn()" value="stop" disabled="disabled"/> -->
</br>
您的名字:<input id="username" type="text" /></br></br>
<input id="textMessage" type="text" size="20" onkeydown="enterSend()" style="border:1;width:400px" />
<input id="sendbtn" type="button" onclick="sendMessage()" value="Send">
<div id="log"></div>
</body>
</html>



java的tomcat7的后台:

package com.hao;

import java.io.DataInputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.net.Socket;
import java.net.UnknownHostException;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;

import javax.servlet.http.HttpServletRequest;

import org.apache.catalina.websocket.MessageInbound;
import org.apache.catalina.websocket.StreamInbound;
import org.apache.catalina.websocket.WebSocketServlet;
import org.apache.catalina.websocket.WsOutbound;

public class HelloWorldWebSocketServlet extends WebSocketServlet {
public static Map<String,MyMessageInbound> mmiList = new HashMap<String,MyMessageInbound>();

protected StreamInbound createWebSocketInbound(String subProtocol,
HttpServletRequest arg1) {
return new MyMessageInbound();
}
public int getUserCount(){
return mmiList.size();
}
private class MyMessageInbound extends MessageInbound {
WsOutbound myoutbound;
String mykey;
@Override
public void onOpen(WsOutbound outbound) {
try {
System.out.println("Open Client.");
this.myoutbound = outbound;
mykey ="open "+System.currentTimeMillis();;
mmiList.put(mykey, this);
System.out.println("mmiList size:"+mmiList.size());
outbound.writeTextMessage(CharBuffer.wrap(mykey));
} catch (IOException e) {
e.printStackTrace();
}
}

@Override
public void onClose(int status) {
System.out.println("Close Client.");
//mmiList.remove(this);
mmiList.remove(mykey);
}

@Override
protected void onBinaryMessage(ByteBuffer arg0) throws IOException {

}

@Override
protected void onTextMessage(CharBuffer message) throws IOException {
// TODO Auto-generated method stub
System.out.println("onText--->" + message.toString());
// for (int i=0;i< mmiList.size();i++ ) {
// MyMessageInbound mmib = (MyMessageInbound) mmiList.get(i);
// CharBuffer buffer = CharBuffer.wrap(message);
// mmib.myoutbound.writeTextMessage(buffer);
// mmib.myoutbound.flush();
// }
for (Map.Entry<String, MyMessageInbound> entry : mmiList.entrySet()) {
//System.out.println("key= " + entry.getKey() + " and value= " + entry.getValue());
MyMessageInbound mmib = (MyMessageInbound) entry.getValue();
// String str = entry.getKey()+message.toString()
CharBuffer buffer = CharBuffer.wrap(message);
mmib.myoutbound.writeTextMessage(buffer);
mmib.myoutbound.flush();
}

/*Socket socket;
String msg = "";
try {
// 向服务器利用Socket发送信息
socket = new Socket("192.168.0.102", 5000);
// socket = new Socket("127.0.0.1",5000);
PrintWriter output = new PrintWriter(socket.getOutputStream());

output.write(message.toString());
output.flush();

// 这里是接收到Server的信息
DataInputStream input = new DataInputStream(
socket.getInputStream());
byte[] b = new byte[1024];
input.read(b);
// Server返回的信息
msg = new String(b).trim();

output.close();
input.close();
socket.close();
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
// 往浏览器发送信息
CharBuffer cb = CharBuffer.wrap(new StringBuilder(msg));
getWsOutbound().writeTextMessage(cb);*/
}
}

public static void main(String[] args) {
Socket socket;
String message = "haoning";
String msg = "";
try {
// 向服务器利用Socket发送信息
socket = new Socket("192.168.0.102", 5000);
// socket = new Socket("127.0.0.1",5000);
PrintWriter output = new PrintWriter(socket.getOutputStream());

output.write(message.toString());
output.flush();

// 这里是接收到Server的信息
DataInputStream input = new DataInputStream(socket.getInputStream());
byte[] b = new byte[1024];
input.read(b);
// Server返回的信息
msg = new String(b).trim();

output.close();
input.close();
socket.close();
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}


web.xml

<servlet>
<servlet-name>wsSnake</servlet-name>
<servlet-class>com.hao.HelloWorldWebSocketServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>wsSnake</servlet-name>
<url-pattern>/websocket/test</url-pattern>
</servlet-mapping>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值