转自:http://blog.youkuaiyun.com/zhou_xw6511/article/details/8479545
这几天研究了下Socket交互。
通过网上的资料做了有关Socket的第一个Demo,虽然不是很成熟,但个人感觉已经相对比较完整了。各类型数据的传输接受都有,其中也做了float类型的(因为我感觉做Unity应该用的着)。
功能方面,为了测试多用户交互,我在Demo上开启了4个Socket 4个线程接受数据。实现了服务端通知用户进入 离开功能。
真机上,需要加上字库,要不无法显示中文。
工程目录:
下面上代码:
客户端代码:
- 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();
- }
- }
- }
- namespace LSocket.Net
- { /**
- *
- * @author feng侠,qq:313785443
- * @date 2010-12-23
- *
- */
- // 描 述:封装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;
- }
- }
- }
- 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;
- }
- }
- }
- namespace LSocket.cmd
- {
- public class CommandID
- {
- /** 登陆消息命令 **/
- public static int LOGIN = 1001;
- }
- }
服务器端代码 Java:
- 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);
- }
- }
- }
- 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;
- }
- }
- 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());
- }
- }
- }
- }
- 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());
- }
- }
- 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;
- }
- }
很简单的demo,有一定的可扩展性,需要工程的可以下载来看,下载链接
http://download.youkuaiyun.com/detail/genius840215/4187126