一.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大多采用小端字節序,所以小端字節序又被稱爲主機字節序,大端字節序也稱爲網絡字節序。