udp通信之c爲客戶端android爲服務端

一.android添加權限

    <uses-permission android:name="android.permission.INTERNET"/>
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
    <uses-permission android:name="android.permission.CHANGE_NETWORK_STATE"/>

二.c爲客戶端發送數據

//結構體數據如下:
typedef struct {
	int cmd; //  消息類型(1.開始 2.傳送內容 3.結束)
	int len;
	char buf[0]; //內容
}subtitle_t;

typedef struct {
	int pos_x; //播放器窗口信息,apk根據播放器窗口(surfaceview)位置信息
	int pos_y; //計算合適的渲染位置;
	int width;
	int height;
}sub_position;

// 發送數據的函數
// 將結構體sub_position放到subtitle_t的buf中發送過去
void sendSubtitleStart(int sockfd,struct sockaddr_in* pDestAddr,socklen_t stlen) 
{
	subtitle_t *pSubtitle;
	sub_position pos;
	memset(&pos,0,sizeof(pos));

	pos.pos_x = 10;
	pos.pos_y = 20;
	pos.width = 1280;
	pos.height = 720;
  
	pSubtitle = (subtitle_t *)malloc(sizeof(subtitle_t) + sizeof(sub_position));
	if(NULL == pSubtitle) {
		Log(LOG_LEVEL_ERR,"##### #### malloc fail #####");
		return ;
	}
	memset(pSubtitle,0,sizeof(subtitle_t) + sizeof(sub_position));
	
	pSubtitle->cmd = 1;
	pSubtitle->len = sizeof(sub_position);
	memcpy(pSubtitle->buf,&pos,pSubtitle->len);
	printf("##### #### pSubtitle->cmd:%d", pSubtitle->cmd);
        printf("##### #### send init #####");
	
	sendto(sockfd,pSubtitle,sizeof(subtitle_t) + sizeof(sub_position),0,(struct sockaddr*)pDestAddr,stlen);

}

//main中代碼如下:
int main(){
    int sockfd;/*cocket句柄和接受到連接後的句柄 */
    char buf[MAX_DATA];//儲存接收數據 
    int n = -1;
    
    sockfd = socket(AF_INET,SOCK_DGRAM,0);/*建立socket SOCK_STREAMSOCK_DGRAM*/ 
    if(sockfd == -1){
        Log(LOG_LEVEL_ERR,"socket failed:%d",errno);
    	return -1;
     }

    //參數意義見上面服務器端 
  struct sockaddr_in dest_addr;/*目標地址信息*/
  memset(&dest_addr,0,sizeof(struct sockaddr_in));
    dest_addr.sin_family=AF_INET;
    dest_addr.sin_port=htons(DEST_PORT);
    dest_addr.sin_addr.s_addr=inet_addr(DEST_IP);
    socklen_t stlen = sizeof(struct sockaddr_in);


    while(1){
	printf("請輸入一個數字,開始發送數據:");        
	char buf=0;         
	scanf("%hhd",&buf);
	sendSubtitleStart(sockfd,&dest_addr, stlen); 
	printf("send success");*/
     }
}

三.服務端接收數據

new Thread(new Runnable() {
            @Override
            public void run() {
                int port = 8913;
                byte[] buf = new byte[512];
                DatagramPacket packet = new DatagramPacket(buf,buf.length);
                try{
                    //1.獲取 datagramSocket 實例,並監聽某個端口
                    DatagramSocket socket = new DatagramSocket(port);
                    Log.d(TAG,"new socket");
                    while (true) {
                        //2.創建一個 udp 的數據包
                        Log.d(TAG,"server將一直等待連接的到來");
                        socket.receive(packet);
                        Log.d(TAG,"=====================");
                        String ip = packet.getAddress().getHostAddress();
                        port = packet.getPort();
                        Log.d(TAG,"客戶端: "+ip+"\tport: "+port);
                        ByteArrayInputStream bis = new ByteArrayInputStream(packet.getData(),0,packet.getLength());
                        DataInputStream dis = new DataInputStream(bis);
                        Log.d(TAG,"cmd: " + int_EndianBigtoLittle(dis.readInt()));
                        Log.d(TAG,"len: " + int_EndianBigtoLittle(dis.readInt()));
                        Log.d(TAG,"x: " + int_EndianBigtoLittle(dis.readInt()));
                        Log.d(TAG,"y: " + int_EndianBigtoLittle(dis.readInt()));
                        Log.d(TAG,"w: " + int_EndianBigtoLittle(dis.readInt()));
                        Log.d(TAG,"h: " + int_EndianBigtoLittle(dis.readInt()));
                    }
                } catch (Exception e) {

                }
            }
        }).start();

// 在網落傳送過程中存在大小端問題,int float需要轉換
 private static int int_EndianBigtoLittle(int value)
    {
        byte[] src = new byte[4];
        src[0] = (byte) ((value>>24)&0xFF);
        src[1] = (byte) ((value>>16)&0xFF);
        src[2] = (byte) ((value>>8)&0xFF);
        src[3] = (byte) ((value)&0xFF);
        return (int) ((src[0]&0xFF)|((src[1]&0xFF)<<8)|((src[2]&0xFF)<<16)|((src[3]&0xFF)<<24));
    }

輸出結果

注意:

  字節序分爲大端字節序和小端字節序,現代PC大多采用小端字節序,所以小端字節序又被稱爲主機字節序,大端字節序也稱爲網絡字節序。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章