zoukankan      html  css  js  c++  java
  • erlang的简单模拟半包的产生

     gen_tcp:linsten()/2使用的是{packet,2/4/8},则gen_tcp模块在接受或者发送时自动除去包头或者自动加上包头。

    本例中使用的是{packet,0}。

    -module(mod_tcp_server_listener)%%监听端口,收到新的socket就启动 mod_client_reader进程

    %%监听端口,收到新的socket就启动 mod_client_reader进程
    -module(mod_tcp_server_listener).
    -include("common.hrl").
    %% ====================================================================
    %% API functions
    %% ====================================================================
    -export([start/1,stop_listen/1]).
    
    
    
    %% ====================================================================
    %% Internal functions
    %% ====================================================================
    
    start(Port)->
    	io:format("hello tcp_server~n"),
    	spawn(fun()-> start_listen(Port) end).
    
    start_listen(Port)->
    	{ok,LSocket}=	gen_tcp:listen(Port, [binary,{active,true},{packet,4}]),
    	socket_accept(LSocket),
    	{ok,LSocket}.
    
    socket_accept(LSocket)->
    	
    	{ok,Socket}=gen_tcp:accept(LSocket),
    
    	Pid=mod_client_reader:start(Socket),
    	ok = gen_tcp:controlling_process(Socket, Pid),	
    	socket_accept(LSocket).
    
    %%tcp_accept(Socket)->
    %%	io:format("hello one accept~n"),
    %%	receive 
    %%			{tcp,Socket,Bin}
    %%			  	->
    			%%	<<Length:32/integer,OneFloat:32/float,OneInt:1/big-unsigned-integer-unit:32,StrLength:2/big-unsigned-integer-unit:8,Left:9/binary>> = Bin,
    			%%		io:format("receive data length: ~w,float:~w,int:~w,str size:~w~n",[Length,OneFloat,OneInt,StrLength]),
    				%%	io:format("receive data: ~w~n",[byte_size(Bin)]),
    			%%		io:format("receive data: ~ts~n",[Left]),
    %%					NewData= <<Bin/binary,Bin/binary>>,
    	%%				gen_tcp:send(Socket, NewData)
    		%%			end,
    			%%{tcp,Socket,?FL_POLICY_REQ}
    %%	tcp_accept(Socket).
    
    stop_listen(LSocket)->
    	gen_tcp:close(LSocket).
    

    module(mod_client_reader):%收到新的socket链接即启动一个该进程

    %%收到新的socket链接即启动一个该进程
    %%该进程负责玩家打开socket后正式进入游戏前的操作,负责登录验证等
    %%该进程代表这客户端的socket,并将客户端到发送来的转给user进程
    -module(mod_client_reader).
    
    %% ====================================================================
    %% API functions
    %% ====================================================================
    -export([start/1,start_io/0]).
    
    %% 记录客户端进程
    -record(client, {
    			  	player_pid = undefined,%玩家的player的进程
    				player_id = 0, %玩家的id
    			   	login  = 0,
    			   	accid  = 0,
    			   	accname = undefined,
    			   	timeout = 0,				% 超时次数
    				sn = 0,						% 服务器号
    				socketN = 0
    				}
    	   ).
    
    %% ====================================================================
    %% Internal functions
    %% ====================================================================
    
    start(Socket)->
    	io:format("client start:~n",[]), 
    	spawn(fun()-> start_accept(Socket) end ).
    
    start_accept(Socket)->
    	receive
    			{tcp,Socket,<<Packet_Length:32,Cmd:32,Str_Length:32,Bin:Str_Length/binary>>}->
    				 
    			%%	io:format(" Data:~w,Bin:~w~n",[byte_size(Data),byte_size(Bin)] ), 
    				
    				 io:format("receive length:~w,cmd:~w,str_length:~w~n",[Packet_Length,Cmd,Str_Length] ),
    				 io:format("Bin:~ts~n",[Bin]),
    				io:format("============one==========================~n",[])		;
    			{tcp,Socket,<<Packet_Length:32,Cmd:32,Str_Length:32,Bin:10/binary,Bin2/binary>>}->
    				 
    			%%	io:format(" Data:~w,Bin:~w~n",[byte_size(Data),byte_size(Bin)] ), 
    				
    				 io:format("receive length:~w,cmd:~w,str_length:~w,bin2_length:~w~n",[Packet_Length,Cmd,Str_Length,byte_size(Bin2)] ),
    				 io:format("Bin:~ts~n",[Bin]),
    				 io:format("Bin2:~ts~n",[Bin2]),
    				io:format("============two==========================~n",[])		
    		end,
    	
    	start_accept(Socket).
    
    
    %%接收来自客户端的数据 - 登陆后进入游戏逻辑
    %%Socket:socket id
    %%Client: client记录
    do_parse_packet(Socket, Client) ->
    	.
    
    
    start_io()->
    	io:format("client start:~n",[]).
    

    以下是java代码:

    package tcp;
    
    /**
     * @author 908204694@qq.com
     *
     */
    public class Door {
    
    	/**
    	 * @param args
    	 */
    	public static void main(String[] args) 
    	{
    		// TODO Auto-generated method stub
    
    		Tcp_Client tcp_client=new Tcp_Client(0);
    		tcp_client.start();
    		
    		
    	}
    
    }
    
    
    ----------------------------------------------------------------------
    
    
    package tcp;
    
    
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.OutputStream;
    
    import java.net.Socket;
    import java.net.UnknownHostException;
    
    
    /**
     * @author 908204694@qq.com
     *
     */
    public class Tcp_Client extends Thread
    {
    	private int id;
    	private int port=5000;
    	
    	public Tcp_Client(int new_id)
    	{
    		this.id=new_id;
    	}
    
    	
    	public  void run() 
    	{
    		// TODO Auto-generated method stub
    		
    		Socket socket=null;
    		try 
    		{
    			socket=new Socket("192.168.1.113",port);
    			System.out.println("连接成功-----");
    		}
    		catch (UnknownHostException e) 
    		{
    			System.out.println("UnknownHostException:"+e.getLocalizedMessage());
    		}
    		catch (IOException e) 
    		{
    			System.out.println("IOException:"+e.getLocalizedMessage());
    		}
    		
    		InputStream input=null;
    		
    		OutputStream output=null;
    	
    		
    		Packet packet=new Packet();
    		packet.writeInt(100);
    		packet.writeString("你好啊1");		
    		byte[] out_bytes=packet.send();;
    		
    		
    		Packet packet1=new Packet();
    		packet1.writeInt(101);
    		packet1.writeString("你好啊2");		
    		byte[] out_bytes1=packet1.send(9);//此值不是固定的值,与位置①的长度一致
    		
    		
    		Packet packet2=new Packet();
    		packet2.writeInt(102);
    		packet2.writeString("你好啊3");		
    		byte[] out_bytes2=packet2.send();;
    		
    		
    		
    		byte[] in_bytes=new byte[100];
    		
    		try 
    		{
    			 input=socket.getInputStream();
    			
    			 
    			 output=socket.getOutputStream();
    			
    		} catch (IOException e) {
    			// TODO Auto-generated catch block
    			e.printStackTrace();
    		}
    
    		try 
    		{
    		
    			output.write(out_bytes);
    			output.flush();
    			
    			output.write(out_bytes1);
    			output.flush();
    			output.write("你好吗".getBytes("UTF-8"));//位置①
    			output.flush();
    			
    			output.write(out_bytes2);
    			output.flush();
    			
    			System.out.println("发送成功--");
    			
    			
    		} catch (IOException e1) 
    		{
    			// TODO Auto-generated catch block
    			e1.printStackTrace();
    			}
    		
    		
    		try 
    		{
    			
    		int read_length=	input.read(in_bytes);
    			
    			System.out.println(new String(in_bytes,0,read_length,"utf8"));
    		} catch (IOException e) {
    			// TODO Auto-generated catch block
    			e.printStackTrace();
    		}
    	}
    
    }
    
    
    
    
    ----------------------------------------------------------------------
    
    
    package tcp;
    
    import java.io.UnsupportedEncodingException;
    import java.nio.ByteBuffer;
    
    
    /**
     * @author 908204694@qq.com
     *
     */
    public class Packet 
    {
    
        private ByteBuffer buff;
        private int length;
        
        public Packet() 
    	{
            this(1024);
        }
    
        public Packet(int size) 
    	{
            length = size;
            buff = ByteBuffer.allocate(length);
        }
    
        public Packet(ByteBuffer buffer) 
    	{
            buff = buffer;
            length = buffer.limit();
        }
    
        public static Packet wrap(ByteBuffer buffer) 
    	{
            return new Packet(buffer);
        }
    
       //写入数据
        public void writeChar(char value) 
    	{
            buff.putChar(value);
        }
    
        public void writeByte(byte value) 
    	{
            buff.put(value);
        }
    
        public void writeFloat(float value) 
    	{
            buff.putFloat(value);
        }
    
        public void writeLong(long value) 
    	{
            buff.putLong(value);
        }
    
        public void writeDouble(double value) 
    	{
            buff.putDouble(value);
        }
    
        public void writeInt(int value) 
    	{
            buff.putInt(value);
        }
    
        public void writeShort(short value) 
    	{
            buff.putShort(value);
        }
    
        public void writeBytes(byte[] bytes) 
    	{
            buff.put(bytes);
        }
    
        /**
         * 
         * @param str
         * 采用UTF-8的编码方式和client端保持一致,utf-8汉字占3位
         */
        public void writeString(String str) 
    	{
          
    		try 
    		{
    			  byte[] str_bytes= str.getBytes("UTF-8");
    			  int len = str_bytes.length;
    		        writeInt(len);
    		        writeBytes(str_bytes);
    		}
    		catch (UnsupportedEncodingException e) 
    		{
    			System.out.println("writeString出现异常");
                System.exit(0);
    		}
            
        }
    
        public void writeString(String str, String charset) 
    	{
            
            try
    		{
                byte[] str_bytes = str.getBytes(charset);
                short len = (short) (str_bytes.length);
                writeShort(len);
                writeBytes(str_bytes);
            }
    		catch (UnsupportedEncodingException e) 
    		{
                System.out.println("writeString出现异常");
                System.exit(0);
            }
        }
    
        //取出数据
        public char readChar() 
    	{
            return buff.getChar();
        }
    
        public byte readByte() 
    	{
            return buff.get();
        }
    
        public float readFloat() 
    	{
            return buff.getFloat();
        }
    
        public long readLong() 
    	{
            return buff.getLong();
        }
    
        public double readDouble()
    	{
            return buff.getFloat();
        }
    
        public int readInt() 
    	{
            return buff.getInt();
        }
    
        public short readShort()
    	{
            return buff.getShort();
        }
    
        public String readString()
    	{
            short len = buff.getShort();
            byte[] _bytes = new byte[len];
            buff.get(_bytes, 0, len);
           
            try 
            {
    			return new String(_bytes,"UTF-8");
    		}
            catch (UnsupportedEncodingException e) 
    		{
    			// TODO Auto-generated catch block
            	System.out.println("readString出现异常");
    		}
            return null;
        }
    
        public String readString(String charset)
    	{
            short len = buff.getShort();
            byte[] _bytes = new byte[len];
            buff.get(_bytes, 0, len);
            try
    		{
                return new String(_bytes, charset);
            }
    		catch (UnsupportedEncodingException e) 
    		{
                System.out.println("readString出现异常");
                e.printStackTrace();
                System.exit(0);
            }
            return new String(_bytes);
        }
    
        public ByteBuffer byteBuffer()
    	{
            return buff;
        }
    
        public ByteBuffer pack() 
    	{
            int l = length();
            ByteBuffer buffer = ByteBuffer.allocate(l);
            if (position() > 0) 
    		{
                flip();
            }
            buffer.put(array(), 0, l);
            buffer.flip();
            return buffer;
        }
    
        public byte[] array()
    	{
            return buff.array();
        }
    
        public int position()
    	{
            return buff.position();
        }
    
        public void flip()
    	{
            if (buff.position() > 0)
    		{
                buff.flip();
            }
        }
    
        public void clear()
    	{
            buff.clear();
            length = 0;
        }
    
        
        public int length()
    	{
            return length - buff.remaining();
        }
    
        
        public int totalSize()
    	{
            return length;
        }
    
        public void outInfo(byte[] bytes)
    	{
            for (int i = 0; i < bytes.length; i++) 
    		{
                System.out.println("---------" + bytes[i]);
            }
        }
        
        //发送
        public byte[] send() 
    	{    	
    	        //发送数据的实际长度
        	int dataLen = buff.limit() - buff.remaining();
        	
            if (buff.position() > 0)
    		{
            	buff.flip();
            }
    
            //发送的bytes,4为数据包的长度信息,为int型,占用4个字节
            ByteBuffer bts = ByteBuffer.allocate(dataLen + 8);
            //写入数据包的长度
            System.out.print("发送的数据长度:"+dataLen);
         //   bts.putInt(dataLen+4);
            bts.putInt(dataLen+4);//在erlang的socket的{packet,2}中头部的数值的大小是包体的长度,因为此次多输个int型的,所以多加了个4,不要误解了
            bts.putInt(dataLen+4);
            //写入数据内容
            bts.put(buff);
    
            if (bts.position() > 0) 
    		{
                bts.flip();
            }
            
            System.out.println("发送给服务端的长度:"+bts.limit() +",告诉服务器的长度"+ (dataLen+4));
            
           return bts.array();        
        }
        
        //发送
        public byte[] send(int length) 
    	{    	
    	        //发送数据的实际长度
        	int dataLen = buff.limit() - buff.remaining();
        	
            if (buff.position() > 0)
    		{
            	buff.flip();
            }
    
            //发送的bytes,4为数据包的长度信息,为int型,占用4个字节
            ByteBuffer bts = ByteBuffer.allocate(dataLen + 8);
            //写入数据包的长度
            System.out.print("原始数据的长度:"+dataLen);
        
            bts.putInt(dataLen+4+length);//在erlang的socket的{packet,2}中头部的数值的大小是包体的长度,因为此次多输个int型的,所以多加了个4,不要误解了
            bts.putInt(dataLen+4+length);
            //写入数据内容
            bts.put(buff);
    
            if (bts.position() > 0) 
    		{
                bts.flip();
            }
            
            System.out.println("发送给服务端的长度:"+bts.remaining()+",告诉服务端的长度:"+ (dataLen+4+length));
            
           return bts.array();        
        }
        
    }
    
  • 相关阅读:
    BestCoder Round #29 1003 (hdu 5172) GTY's gay friends [线段树 判不同 预处理 好题]
    POJ 1182 食物链 [并查集 带权并查集 开拓思路]
    Codeforces Round #288 (Div. 2) E. Arthur and Brackets [dp 贪心]
    Codeforces Round #287 (Div. 2) E. Breaking Good [Dijkstra 最短路 优先队列]
    Codeforces Round #287 (Div. 2) D. The Maths Lecture [数位dp]
    NOJ1203 最多约数问题 [搜索 数论]
    poj1426
    POJ 1502 MPI Maelstrom [最短路 Dijkstra]
    POJ 2785 4 Values whose Sum is 0 [二分]
    浅析group by,having count()
  • 原文地址:https://www.cnblogs.com/ribavnu/p/3437608.html
Copyright © 2011-2022 走看看