这几天研究了下Socket交互。
通过网上的资料做了有关Socket的第一个Demo,虽然不是很成熟,但个人感觉已经相对比较完整了。各类型数据的传输接受都有,其中也做了float类型的(因为我感觉做Unity应该用的着)。
功能方面,为了测试多用户交互,我在Demo上开启了4个Socket 4个线程接受数据。实现了服务端通知用户进入 离开功能。
真机上,需要加上字库,要不无法显示中文。
工程目录:
http://my.csdn.net/uploads/201203/30/1333093902_9843.png
下面上代码:
客户端代码Unity3d:
1.SocketDemo
.cs
using
UnityEngine;
using
System;
using
System.Collections;
using
LSocket.Net;
using
LSocket.Type;
using
LSocket.cmd;
public class SocketDemo :
MonoBehaviour
{
public
UnitySocket[] socket;
public
String[] textAreaString;
public
String[] textFieldString;
public
GUISkin mySkin;
// Use
this for initialization
void
Start()
{
socket = new
UnitySocket[4];
textAreaString = new
String[12];
for (int i = 0; i
< 12; i++)
{
textAreaString[i] = "";
}
textFieldString = new
String[4];
for(int
i=0;i<4;i++){
textFieldString[i] = "";
}
}
// Update
is called once per frame
void
Update()
{
}
void
OnGUI()
{
GUI.skin =
mySkin;
for (int i = 0; i
< 4; i++)
{
String s = textAreaString[i * 3] + "\n" +
textAreaString[i * 3 + 1] + "\n" + textAreaString[i * 3 +
2];
GUI.TextArea(new Rect(i % 2 * Screen.width / 2,
i / 2 * (Screen.height / 2) + 50, 100, 60), s);
textFieldString[i] = GUI.TextField(new Rect(i %
2 * Screen.width / 2+50, i / 2 * (Screen.height / 2), 100, 20),
textFieldString[i]);
if (GUI.Button(new Rect(i % 2 * Screen.width /
2, i / 2 * (Screen.height / 2), 40, 20), "连接"))
{
socket[i]
= null;
socket[i]
= new UnitySocket();
socket[i].SocketConnection("192.168.0.8", 10000, this,
i);
socket[i].DoLogin(textFieldString[i]);
}
else if (GUI.Button(new Rect(i % 2 *
Screen.width / 2, i / 2 *( Screen.height / 2) + 25, 40, 20),
"关闭"))
{
if
(socket[i] != null)
{
socket[i].close();
socket[i] =
null;
}
}
}
if (GUI.Button(new
Rect(Screen.width - 60, Screen.height - 30, 60, 30), "退出"))
{
Application.Quit();
}
}
}
2.UnitySocket.cs
namespace
LSocket.Net
{
// 描 述:封装c#
socket数据传输协议
using
UnityEngine;
using
System;
using
System.Net.Sockets;
using
System.Net;
using
System.Collections;
using
System.Text;
using System.Threading;
using
LSocket.Type;
using
LSocket.cmd;
class SocketThread
{
UnitySocket socket;
SocketDemo
demo;
int
idx;
public
SocketThread(UnitySocket socket, SocketDemo demo, int
idx)
{
this.socket =
socket;
this.demo = demo;
this.idx = idx;
}
public
void run()
{
while (true)
{
try
{
String s =
socket.ReceiveString();
demo.textAreaString[idx * 3] = demo.textAreaString[idx * 3 +
1];
demo.textAreaString[idx * 3 + 1] = demo.textAreaString[idx * 3 +
2];
demo.textAreaString[idx * 3 + 2] = s;
MonoBehaviour.print(s + " " + idx);
}
catch (Exception e)
{
MonoBehaviour.print(e.ToString());
socket.t.Abort();
}
}
}
}
public class
UnitySocket
{
public
Socket mSocket = null;
public
Thread t=null;
private
SocketThread st=null;
public
SocketDemo demo=null;
public
UnitySocket()
{
}
public void
SocketConnection(string LocalIP, int LocalPort,SocketDemo demo,int
idx)
{
this.demo=demo;
mSocket = new
Socket(AddressFamily.InterNetwork, SocketType.Stream,
ProtocolType.Tcp);
try
{
IPAddress ip =
IPAddress.Parse(LocalIP);
IPEndPoint ipe = new IPEndPoint(ip,
LocalPort);
mSocket.Connect(ipe);
st =new SocketThread(this, demo,
idx);
t = new Thread(new
ThreadStart(st.run));
t.Start();
}
catch (Exception
e)
{
MonoBehaviour.print(e.ToString());
}
}
public
void close(){
mSocket.Close(0);
mSocket=null;
}
public
void DoLogin(String userName){
try
{
Send(CommandID.LOGIN);
Send(userName);
}catch(Exception
e){
MonoBehaviour.print(e.ToString());
}
}
public
void Send(float data){
byte[] longth =
TypeConvert.getBytes(data, true);
mSocket.Send(longth);
}
public
float ReceiveFloat()
{
byte[] recvBytes = new
byte[4];
mSocket.Receive(recvBytes, 4,
0);//从服务器端接受返回信息
float data =
TypeConvert.getFloat(recvBytes, true);
return data;
}
public void
Send(short data)
{
byte[]
longth=TypeConvert.getBytes(data,true);
mSocket.Send(longth);
}
public void
Send(long data)
{
byte[]
longth=TypeConvert.getBytes(data,true);
mSocket.Send(longth);
}
public void
Send(int data)
{
byte[]
longth=TypeConvert.getBytes(data,true);
mSocket.Send(longth);
}
public void
Send(string data)
{
byte[]
longth=Encoding.UTF8.GetBytes(data);
Send(longth.Length);
mSocket.Send(longth);
}
public short
ReceiveShort()
{
byte[]
recvBytes = new byte[2];
mSocket.Receive(recvBytes,2,0);//从服务器端接受返回信息
short
data=TypeConvert.getShort(recvBytes,true);
return
data;
}
public int
ReceiveInt()
{
byte[]
recvBytes = new byte[4];
mSocket.Receive(recvBytes,4,0);//从服务器端接受返回信息
int
data=TypeConvert.getInt(recvBytes,true);
return
data;
}
public long
ReceiveLong()
{
byte[]
recvBytes = new byte[8];
mSocket.Receive(recvBytes,8,0);//从服务器端接受返回信息
long
data=TypeConvert.getLong(recvBytes,true);
return
data;
}
public String
ReceiveString()
{
int length
= ReceiveInt();
MonoBehaviour.print("Stringlen="+length);
byte[]
recvBytes = new byte[length];
mSocket.Receive(recvBytes,length,0);//从服务器端接受返回信息
String data
= Encoding.UTF8.GetString(recvBytes);
return
data;
}
}
}
3.TypeConvert.cs
namespace
LSocket.Type
{
using UnityEngine;
using System.Collections;
public class TypeConvert
{
public
TypeConvert()
{
}
public
static byte[] getBytes(float s,bool asc){
int buf = (int)(s *
100);
return
getBytes(buf,asc);
}
public static float getFloat(byte[] buf,bool
asc){
int i=getInt(buf,asc);
float s=(float)i;
return s/100;
}
public
static byte[] getBytes(short s, bool asc)
{
byte[] buf = new
byte[2];
if (asc)
{
for (int i = buf.Length - 1; i >=
0; i--)
{
buf[i] =
(byte)(s & 0x00ff);
s
>>= 8;
}
}
else
{
for (int i = 0; i < buf.Length;
i++)
{
buf[i] =
(byte)(s & 0x00ff);
s
>>= 8;
}
}
return buf;
}
public
static byte[] getBytes(int s, bool asc)
{
byte[] buf = new
byte[4];
if (asc)
for (int i = buf.Length - 1; i >=
0; i--)
{
buf[i] =
(byte)(s & 0x000000ff);
s
>>= 8;
}
else
for (int i = 0; i < buf.Length;
i++)
{
buf[i] =
(byte)(s & 0x000000ff);
s
>>= 8;
}
return buf;
}
public
static byte[] getBytes(long s, bool asc)
{
byte[] buf = new
byte[8];
if (asc)
for (int i = buf.Length - 1; i >=
0; i--)
{
buf[i] =
(byte)(s & 0x00000000000000ff);
s
>>= 8;
}
else
for (int i = 0; i < buf.Length;
i++)
{
buf[i] =
(byte)(s & 0x00000000000000ff);
s
>>= 8;
}
return buf;
}
public
static short getShort(byte[] buf, bool asc)
{
if (buf == null)
{
//throw new IllegalArgumentException("byte array
is null!");
}
if (buf.Length
> 2)
{
//throw new IllegalArgumentException("byte array
size > 2 !");
}
short r = 0;
if (!asc)
for (int i = buf.Length - 1; i >=
0; i--)
{
r
<<= 8;
r |=
(short)(buf[i] & 0x00ff);
}
else
for (int i = 0; i < buf.Length;
i++)
{
r
<<= 8;
r |=
(short)(buf[i] & 0x00ff);
}
return r;
}
public
static int getInt(byte[] buf, bool asc)
{
if (buf == null)
{
// throw new IllegalArgumentException("byte
array is null!");
}
if (buf.Length
> 4)
{
//throw new IllegalArgumentException("byte array
size > 4 !");
}
int r = 0;
if (!asc)
for (int i = buf.Length - 1; i >=
0; i--)
{
r
<<= 8;
r |=
(buf[i] & 0x000000ff);
}
else
for (int i = 0; i < buf.Length;
i++)
{
r
<<= 8;
r |=
(buf[i] & 0x000000ff);
}
return r;
}
public
static long getLong(byte[] buf, bool asc)
{
if (buf == null)
{
//throw new IllegalArgumentException("byte array
is null!");
}
if (buf.Length
> 8)
{
//throw new IllegalArgumentException("byte array
size > 8 !");
}
long r = 0;
if (!asc)
for (int i = buf.Length - 1; i >=
0; i--)
{
r
<<= 8;
r |=
(buf[i] & 0x00000000000000ff);
}
else
for (int i = 0; i < buf.Length;
i++)
{
r
<<= 8;
r |=
(buf[i] & 0x00000000000000ff);
}
return r;
}
}
}
4.CommandID.cs
namespace
LSocket.cmd
{
public class CommandID
{
public static int LOGIN = 1001;
}
}
服务器端代码 Java:
(1).
package
com.unity.socket;
import
java.net.ServerSocket;
import
java.net.Socket;
import
java.util.HashMap;
public class SocketServer
{
private
HashMap<String,User>
userMap;
public
SocketServer(){
userMap=new HashMap<String,
User>();
}
public static void main(String[]
args){
new
SocketServer().startServer();
}
public void startServer()
{
try
{
ServerSocket serverSocket =
new ServerSocket(10000);
System.out.println("服务器开启");
while
(true){
Socket socket =
serverSocket.accept();
System.out.println("有用户登陆进来了");
new
UserThread(socket,userMap).start();
}
}catch
(Exception e){
System.out.println("服务器出现异常!" +
e);
}
}
}
(2).
package
com.unity.socket;
import
java.net.Socket;
public class User
{
private String name;
private Socket socket;
public String getName() {
return
name;
}
public void setName(String name)
{
this.name
= name;
}
public Socket getSocket() {
return
socket;
}
public void setSocket(Socket socket)
{
this.socket = socket;
}
}
(3).
package
com.unity.socket;
import
java.io.*;
import
java.net.Socket;
import
java.util.Iterator;
import
java.io.ByteArrayOutputStream;
import
java.io.DataOutputStream;
import
java.util.HashMap;
public class UserThread
extends Thread{
public static final int ERROR
= 0;
public static final int LOGIN
= 1001;
private Socket socket;
private
HashMap<String,User>
userMap;
private User user;
private ByteArrayOutputStream
byteOutput;
private DataOutputStream
output;
private DataInputStream
input;
public UserThread(Socket
socket,HashMap<String,User>
userMap){
this.socket=socket;
this.userMap=userMap;
}
//重新初始化2个新的output
private void
initOutput()
{
byteOutput = new
ByteArrayOutputStream();
output = new
DataOutputStream(byteOutput);
}
public void sendAllUser(byte[] bytes) throws
Exception
{
for(Iterator<User>
it = userMap.values().iterator();
it.hasNext();)
{
sendMessage(it.next().getSocket(),bytes);
}
}
public void sendMessage(Socket socket,byte[]
bytes) throws Exception
{
DataOutputStream dataOutput =
new DataOutputStream(socket.getOutputStream());
dataOutput.write(bytes);
dataOutput.flush();
}
public short readShort()throws
IOException{
byte[] buf=new byte[2];
input.read(buf);
return
ConvertType.getShort(buf,true);
}
public int readInt()throws
IOException{
byte[] buf=new byte[4];
input.read(buf);
return ConvertType.getInt(buf,
true);
}
public long readLong()throws
IOException{
byte[] buf=new byte[8];
input.read(buf);
return ConvertType.getLong(buf,
true);
}
public float readFloat()throws
IOException{
byte[] buf=new byte[4];
input.read(buf);
return ConvertType.getFloat(buf,
true);
}
public String readString()throws
IOException{
int length=readInt();
byte[] buf=new byte[length];
input.read(buf);
return new String(buf);
}
public void run(){
try{
input = new
DataInputStream(socket.getInputStream()) ;
while
(true){
int cmd=0;
cmd=readInt();
System.out.println("命令号:"+cmd);
if(cmd==ERROR){
//收空包
userMap.remove(user.getName());
Message
msg=new Message();
msg.writeString(user.getName()+" 离开");
System.out.println(user.getName()+" 离开");
try{
sendAllUser(msg.getBuff().array());
}catch
(Exception ex){
System.out.println("sendAllUserErr:
"+ex.toString());
}
break;
}
switch (cmd){
case
LOGIN:
System.out.println("读取用户名");
String userName =
readString();
user = new
User();
user.setName(userName);
user.setSocket(socket);
System.out.println(userName);
if(userMap.containsKey(userName)) {
Message msg=new Message();
msg.writeString("昵称重复");
sendMessage(socket,msg.getBuff().array());
msg.clear();
msg=null;
}else{
System.out.println("有新用户进入:" +
userName);
userMap.put(userName,
user);
initOutput();
Message msg=new Message();
msg.writeString("连接成功");
sendMessage(socket,msg.getBuff().array());
msg.clear();
msg=null;
}
break;
}
}
}catch
(Exception e){
e.printStackTrace();
userMap.remove(user.getName());
Message
msg=new Message();
msg.writeString(user.getName()+"
离开");
System.out.println(user.getName()+" 离开");
try{
sendAllUser(msg.getBuff().array());
}catch (Exception
ex){
System.out.println("sendAllUserErr:
"+ex.toString());
}
}
}
}
(4).
package
com.unity.socket;
import
java.nio.ByteBuffer;
import
com.unity.socket.ConvertType;
public class Message
{
private ByteBuffer buf;
public Message(){
buf=ByteBuffer.allocate(0);
}
public ByteBuffer getBuff(){
return
buf;
}
public void clear(){
buf.clear();
}
public void addSize(int
len){
ByteBuffer
tmpbuf=ByteBuffer.allocate(buf.capacity()+len);
buf=null;
buf=tmpbuf;
}
public void writeByte(byte
b){
addSize(1);
buf.put(b);
}
public void write(byte[] b){
addSize(b.length);
buf.put(b);
}
public void writeShort(short
b){
addSize(2);
buf.put(ConvertType.getBytes(b,true));
}
public void writeInt(int b){
addSize(4);
buf.put(ConvertType.getBytes(b,true));
}
public void writeLong(long
b){
addSize(8);
buf.put(ConvertType.getBytes(b,true));
}
public void writeFloat(float
b){
addSize(4);
buf.put(ConvertType.getBytes(b,true)) ;
}
public void writeString(String
s){
byte[] b=
new byte[200];
b=s.getBytes();
addSize(4+b.length);
buf.put(ConvertType.getBytes(b.length,true));
buf.put(s.getBytes());
}
}
(5).
package
com.unity.socket;
public class
ConvertType
{
public
ConvertType()
{
}
public final static byte[] getBytes(float
s,boolean asc){
int
buf=(int)(s*100);
return
getBytes(buf,asc);
}
public final static float
getFloat(byte[] buf,boolean asc){
int
i=getInt(buf,asc);
float
s=(float)i;
return
s/100;
}
public final static byte[]
getBytes(short s, boolean asc)
{
byte[] buf = new byte[2];
if (asc)
{
for (int i = buf.length - 1; i >=
0; i--)
{
buf[i] = (byte) (s &
0x00ff);
s
>>= 8;
}
}
else
{
for (int i = 0; i < buf.length;
i++)
{
buf[i] =
(byte) (s & 0x00ff);
s
>>= 8;
}
}
return buf;
}
public
final static byte[] getBytes(int s, boolean asc)
{
byte[] buf = new byte[4];
if (asc)
for (int i = buf.length - 1; i
>= 0; i--) {
buf[i] =
(byte) (s & 0x000000ff);
s
>>= 8;
}
else
for (int i = 0; i
< buf.length; i++) {
buf[i] =
(byte) (s & 0x000000ff);
s
>>= 8;
}
return buf;
}
public
final static byte[] getBytes(long s, boolean asc)
{
byte[] buf = new byte[8];
if (asc)
for (int i = buf.length - 1; i
>= 0; i--) {
buf[i] =
(byte) (s &
0x00000000000000ff);
s
>>= 8;
}
else
for (int i = 0; i
< buf.length; i++) {
buf[i] =
(byte) (s &
0x00000000000000ff);
s
>>= 8;
}
return buf;
}
public
final static short getShort(byte[] buf, boolean
asc)
{
if (buf ==
null)
{
throw new
IllegalArgumentException("byte array is
null!");
}
if (buf.length >
2)
{
throw new
IllegalArgumentException("byte array size > 2
!");
}
short r = 0;
if (!asc)
for (int i = buf.length - 1; i
>= 0; i--) {
r
<<= 8;
r |=
(buf[i] & 0x00ff);
}
else
for (int i = 0; i
< buf.length; i++) {
r
<<= 8;
r |=
(buf[i] & 0x00ff);
}
return r;
}
public
final static int getInt(byte[] buf, boolean asc)
{
if (buf == null) {
throw new
IllegalArgumentException("byte array is
null!");
}
if (buf.length > 4)
{
throw new
IllegalArgumentException("byte array size > 4
!");
}
int r = 0;
if (!asc)
for (int i = buf.length - 1; i
>= 0; i--) {
r
<<= 8;
r |=
(buf[i] & 0x000000ff);
}
else
for (int i = 0; i
< buf.length; i++) {
r
<<= 8;
r |=
(buf[i] & 0x000000ff);
}
return r;
}
public
final static long getLong(byte[] buf, boolean asc)
{
if (buf == null) {
throw new
IllegalArgumentException("byte array is
null!");
}
if (buf.length > 8)
{
throw new
IllegalArgumentException("byte array size > 8
!");
}
long r = 0;
if (!asc)
for (int i = buf.length - 1; i
>= 0; i--) {
r
<<= 8;
r |=
(buf[i] & 0x00000000000000ff);
}
else
for (int i = 0; i
< buf.length; i++) {
r
<<= 8;
r |=
(buf[i] & 0x00000000000000ff);
}
return r;
}
}