久久国产成人av_抖音国产毛片_a片网站免费观看_A片无码播放手机在线观看,色五月在线观看,亚洲精品m在线观看,女人自慰的免费网址,悠悠在线观看精品视频,一级日本片免费的,亚洲精品久,国产精品成人久久久久久久

分享

socket 發(fā)送結(jié)構(gòu)體數(shù)據(jù)

 禁忌石 2019-03-26

  Socket中的send函數(shù)可以發(fā)送字符串,但不能直接發(fā)送結(jié)構(gòu)體,,因此在發(fā)送端先把結(jié)構(gòu)體轉(zhuǎn)成字符串,,然后用send發(fā)送,在接收端recv字符串,,再轉(zhuǎn)換成原先的結(jié)構(gòu)體,這個(gè)就是解決問題的主要思路,,實(shí)現(xiàn)中要注意的問題在下文闡述,。

  為了客戶端之間能夠互相通信,實(shí)現(xiàn)私聊,,我采用服務(wù)器轉(zhuǎn)發(fā)的方式,,因此用戶發(fā)送的每條消息中除了消息主體外,還必須包含有發(fā)送者,、接收者ID等信息,,如此采用結(jié)構(gòu)體便是最佳的辦法了,。我定義的結(jié)構(gòu)體如下:

雙擊代碼全選
1
2
3
4
5
6
7
struct send_info
{
char info_from[20]; //發(fā)送者ID
char info_to[20]; //接收者ID
int info_length; //發(fā)送的消息主體的長度
char info_content[1024]; //消息主體
};

  發(fā)送端主要代碼(為了簡潔說明問題,我把用戶輸入的內(nèi)容,、長度等驗(yàn)證的代碼去掉了):

雙擊代碼全選
1
2
3
4
5
6
7
8
9
10
11
struct send_info info1; //定義結(jié)構(gòu)體變量
printf("This is client,please input message:");
//從鍵盤讀取用戶輸入的數(shù)據(jù),,并寫入info1.info_content
memset(info1.info_content,0,sizeof(info1.info_content));//清空緩存
info1.info_length=read(STDIN_FILENO,info1.info_content,1024) - 1;//讀取用戶輸入的數(shù)據(jù)
  
memset(snd_buf,0,1024);//清空發(fā)送緩存,不清空的話可能導(dǎo)致接收時(shí)產(chǎn)生亂碼,,
//或者如果本次發(fā)送的內(nèi)容少于上次的話,,snd_buf中會(huì)包含有上次的內(nèi)容
  
memcpy(snd_buf,&info1,sizeof(info1)); //結(jié)構(gòu)體轉(zhuǎn)換成字符串
send(connect_fd,snd_buf,sizeof(snd_buf),0);//發(fā)送信息

接收端主要代碼:

雙擊代碼全選
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
struct send_info clt; //定義結(jié)構(gòu)體變量
  
memset(recv_buf,'z',1024);//清空緩存
recv(fd,recv_buf,1024,0 );//讀取數(shù)據(jù)
  
memset(&clt,0,sizeof(clt));//清空結(jié)構(gòu)體
memcpy(&clt,recv_buf,sizeof(clt));//把接收到的信息轉(zhuǎn)換成結(jié)構(gòu)體
  
clt.info_content[clt.info_length]='';
//消息內(nèi)容結(jié)束,沒有這句的話,,可能導(dǎo)致消息亂碼或輸出異常
//有網(wǎng)友建議說傳遞的結(jié)構(gòu)體中盡量不要有string類型的字段,,估計(jì)就是串尾符定位的問題
  
if(clt.info_content) //判斷接收內(nèi)容并輸出
printf("nclt.info_from is %snclt.info_to is %snclt.info_content is%snclt.info_length is %dn",clt.info_from,clt.info_to,clt.info_content,clt.info_length);
//至此,結(jié)構(gòu)體的發(fā)送與接收已經(jīng)順利結(jié)束了

 c/c++通過socket發(fā)送結(jié)構(gòu)可以直接先將結(jié)構(gòu)轉(zhuǎn)化到內(nèi)存中,,再通過send直接發(fā)送,。

  在網(wǎng)絡(luò)通訊過程中往往涉及一些有關(guān)聯(lián)的參數(shù)傳遞,例如數(shù)組,,結(jié)構(gòu)體之類的,。對(duì)于結(jié)構(gòu)體其實(shí)方法挺簡單,由于結(jié)構(gòu)體對(duì)象在內(nèi)存中分配的空間都是連續(xù)的,,所以可以將整個(gè)結(jié)構(gòu)體直接轉(zhuǎn)化成字符串發(fā)送,,到了接收方再將這個(gè)字符串還原成結(jié)構(gòu)體就大功告成了。

  首先,,我們建立一個(gè)結(jié)構(gòu)體,。

  struct UsrData{

  char usr_id[16];

  char usr_pwd[16];

  char usr_nickname[16];

  };

  當(dāng)然,這個(gè)結(jié)構(gòu)體在發(fā)送方與接收方都必須聲明,。

  接下來創(chuàng)建對(duì)象并初始化,,然后發(fā)送。

  UsrData sendUser;

  memcpy( sendUser.usr_id, “100001”, sizeof(“100001”) );

  memcpy( sendUser.usr_pwd, “123456”, sizeof(“123456”) );

  memcpy( sendUser.usr_nickname, “Rock”, sizeof(“Rock”) );

  send( m_socket, (char *)&sendUser, sizeof(UsrData), 0 );

  這樣發(fā)送方就已經(jīng)將這個(gè)mUser對(duì)象以字符串的形式發(fā)送出去了,。

  最后在接收方做接收,。

  char buffer[1024];

  UsrData recvUser;

  recv( m_socket, buffer, sizeof(buffer), 0 );

  memcpy( &recvUser, buffer, sizeof(buffer) );

  這樣得到的recvUser對(duì)象里的數(shù)據(jù)與sendUser相同了。具體原因其實(shí)很簡單,,就是因?yàn)榻Y(jié)構(gòu)體對(duì)象的內(nèi)存區(qū)域連續(xù),,同時(shí)每個(gè)成員的區(qū)塊大小都分配好了,當(dāng)接收完自己的區(qū)塊,,其實(shí)自己的數(shù)據(jù)已經(jīng)接收完成,。挺簡單的,但還是挺有用的,。 :smile:

      也可以直接將內(nèi)存寫到文件中:

      int cfg_fd = -1;
      cfg_fd = open(HD4100_CONFIG_FILE, O_RDWR|O_CREAT|O_TRUNC);
      if (cfg_fd < 0) 
      {
           printf("open config file failed/n");
           return -1;
      }
      write(cfg_fd, para, sizeof(hd4100_rec_t));  //hd4100_rec_t是自定義的結(jié)構(gòu)
      close(cfg_fd); 
      printf("the para which is written to the config file:/n");

      read(cfg_fd, &hd4100_config, sizeof(hd4100_rec_t)); //從文件讀內(nèi)容到內(nèi)存中
      close(cfg_fd);

       包含引用類型或值類型的結(jié)構(gòu)或?qū)ο鬅o法通過以上方法直接發(fā)送,,而必須通過序列化的方式轉(zhuǎn)化為二進(jìn)制流發(fā)送和接收。如c# Socket傳送序列化Struct示例:

傳數(shù)據(jù),下面給一個(gè)傳送struct的例子. 
首先:把struct寫到一個(gè)單獨(dú)的類中.編譯成dll 
using System; 
[Serializable] 
public struct USER_INF 

public long id; 
public string nickname; 
public string ***; 
public int age; 
public string address; 
public string password; 

然后在你的服務(wù)器端和客戶端都添加這個(gè)dll. 
下面是服務(wù)器端發(fā)送這個(gè)序列化的struct 
while(true) 

Socket s=tcpl.AcceptSocket(); 
BinaryFormatter bf; 
bf = new BinaryFormatter(); 
MemoryStream stream = new MemoryStream(); 
USER_INF user; 
user.id=0; 
user.nickname="Pony"; 
user.***="?"; 
user.age=20; 
user.address="192.168.7.91"; 
user.password="123456"; 
bf.Serialize(stream,user); 
byte[] buff = stream.ToArray(); 
s.Send(buff,buff.Length,0); 
s.Close(); 
Console.WriteLine("?????!"); 


一下是client端接收到數(shù)據(jù)后反序列化 
BinaryFormatter bf; 
bf = new BinaryFormatter(); 
USER_INF user=(USER_INF)bf.Deserialize(s);

  Socket中的send函數(shù)可以發(fā)送字符串,,但不能直接發(fā)送結(jié)構(gòu)體,,因此在發(fā)送端先把結(jié)構(gòu)體轉(zhuǎn)成字符串,,然后用send發(fā)送,在接收端recv字符串,,再轉(zhuǎn)換成原先的結(jié)構(gòu)體,,這個(gè)就是解決問題的主要思路,實(shí)現(xiàn)中要注意的問題在下文闡述,。

  為了客戶端之間能夠互相通信,,實(shí)現(xiàn)私聊,我采用服務(wù)器轉(zhuǎn)發(fā)的方式,,因此用戶發(fā)送的每條消息中除了消息主體外,,還必須包含有發(fā)送者、接收者ID等信息,,如此采用結(jié)構(gòu)體便是最佳的辦法了,。我定義的結(jié)構(gòu)體如下:

雙擊代碼全選
1
2
3
4
5
6
7
struct send_info
{
char info_from[20]; //發(fā)送者ID
char info_to[20]; //接收者ID
int info_length; //發(fā)送的消息主體的長度
char info_content[1024]; //消息主體
};

  發(fā)送端主要代碼(為了簡潔說明問題,我把用戶輸入的內(nèi)容,、長度等驗(yàn)證的代碼去掉了):

雙擊代碼全選
1
2
3
4
5
6
7
8
9
10
11
struct send_info info1; //定義結(jié)構(gòu)體變量
printf("This is client,please input message:");
//從鍵盤讀取用戶輸入的數(shù)據(jù),,并寫入info1.info_content
memset(info1.info_content,0,sizeof(info1.info_content));//清空緩存
info1.info_length=read(STDIN_FILENO,info1.info_content,1024) - 1;//讀取用戶輸入的數(shù)據(jù)
  
memset(snd_buf,0,1024);//清空發(fā)送緩存,不清空的話可能導(dǎo)致接收時(shí)產(chǎn)生亂碼,,
//或者如果本次發(fā)送的內(nèi)容少于上次的話,,snd_buf中會(huì)包含有上次的內(nèi)容
  
memcpy(snd_buf,&info1,sizeof(info1)); //結(jié)構(gòu)體轉(zhuǎn)換成字符串
send(connect_fd,snd_buf,sizeof(snd_buf),0);//發(fā)送信息

接收端主要代碼:

雙擊代碼全選
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
struct send_info clt; //定義結(jié)構(gòu)體變量
  
memset(recv_buf,'z',1024);//清空緩存
recv(fd,recv_buf,1024,0 );//讀取數(shù)據(jù)
  
memset(&clt,0,sizeof(clt));//清空結(jié)構(gòu)體
memcpy(&clt,recv_buf,sizeof(clt));//把接收到的信息轉(zhuǎn)換成結(jié)構(gòu)體
  
clt.info_content[clt.info_length]='';
//消息內(nèi)容結(jié)束,沒有這句的話,,可能導(dǎo)致消息亂碼或輸出異常
//有網(wǎng)友建議說傳遞的結(jié)構(gòu)體中盡量不要有string類型的字段,,估計(jì)就是串尾符定位的問題
  
if(clt.info_content) //判斷接收內(nèi)容并輸出
printf("nclt.info_from is %snclt.info_to is %snclt.info_content is%snclt.info_length is %dn",clt.info_from,clt.info_to,clt.info_content,clt.info_length);
//至此,結(jié)構(gòu)體的發(fā)送與接收已經(jīng)順利結(jié)束了

 c/c++通過socket發(fā)送結(jié)構(gòu)可以直接先將結(jié)構(gòu)轉(zhuǎn)化到內(nèi)存中,,再通過send直接發(fā)送,。

  在網(wǎng)絡(luò)通訊過程中往往涉及一些有關(guān)聯(lián)的參數(shù)傳遞,例如數(shù)組,,結(jié)構(gòu)體之類的,。對(duì)于結(jié)構(gòu)體其實(shí)方法挺簡單,由于結(jié)構(gòu)體對(duì)象在內(nèi)存中分配的空間都是連續(xù)的,,所以可以將整個(gè)結(jié)構(gòu)體直接轉(zhuǎn)化成字符串發(fā)送,,到了接收方再將這個(gè)字符串還原成結(jié)構(gòu)體就大功告成了。

  首先,,我們建立一個(gè)結(jié)構(gòu)體,。

  struct UsrData{

  char usr_id[16];

  char usr_pwd[16];

  char usr_nickname[16];

  };

  當(dāng)然,這個(gè)結(jié)構(gòu)體在發(fā)送方與接收方都必須聲明,。

  接下來創(chuàng)建對(duì)象并初始化,然后發(fā)送,。

  UsrData sendUser;

  memcpy( sendUser.usr_id, “100001”, sizeof(“100001”) );

  memcpy( sendUser.usr_pwd, “123456”, sizeof(“123456”) );

  memcpy( sendUser.usr_nickname, “Rock”, sizeof(“Rock”) );

  send( m_socket, (char *)&sendUser, sizeof(UsrData), 0 );

  這樣發(fā)送方就已經(jīng)將這個(gè)mUser對(duì)象以字符串的形式發(fā)送出去了,。

  最后在接收方做接收,。

  char buffer[1024];

  UsrData recvUser;

  recv( m_socket, buffer, sizeof(buffer), 0 );

  memcpy( &recvUser, buffer, sizeof(buffer) );

  這樣得到的recvUser對(duì)象里的數(shù)據(jù)與sendUser相同了。具體原因其實(shí)很簡單,,就是因?yàn)榻Y(jié)構(gòu)體對(duì)象的內(nèi)存區(qū)域連續(xù),,同時(shí)每個(gè)成員的區(qū)塊大小都分配好了,當(dāng)接收完自己的區(qū)塊,,其實(shí)自己的數(shù)據(jù)已經(jīng)接收完成,。挺簡單的,但還是挺有用的,。 :smile:

      也可以直接將內(nèi)存寫到文件中:

      int cfg_fd = -1;
      cfg_fd = open(HD4100_CONFIG_FILE, O_RDWR|O_CREAT|O_TRUNC);
      if (cfg_fd < 0) 
      {
           printf("open config file failed/n");
           return -1;
      }
      write(cfg_fd, para, sizeof(hd4100_rec_t));  //hd4100_rec_t是自定義的結(jié)構(gòu)
      close(cfg_fd); 
      printf("the para which is written to the config file:/n");

      read(cfg_fd, &hd4100_config, sizeof(hd4100_rec_t)); //從文件讀內(nèi)容到內(nèi)存中
      close(cfg_fd);

       包含引用類型或值類型的結(jié)構(gòu)或?qū)ο鬅o法通過以上方法直接發(fā)送,,而必須通過序列化的方式轉(zhuǎn)化為二進(jìn)制流發(fā)送和接收。如c# Socket傳送序列化Struct示例:

傳數(shù)據(jù),下面給一個(gè)傳送struct的例子. 
首先:把struct寫到一個(gè)單獨(dú)的類中.編譯成dll 
using System; 
[Serializable] 
public struct USER_INF 

public long id; 
public string nickname; 
public string ***; 
public int age; 
public string address; 
public string password; 

然后在你的服務(wù)器端和客戶端都添加這個(gè)dll. 
下面是服務(wù)器端發(fā)送這個(gè)序列化的struct 
while(true) 

Socket s=tcpl.AcceptSocket(); 
BinaryFormatter bf; 
bf = new BinaryFormatter(); 
MemoryStream stream = new MemoryStream(); 
USER_INF user; 
user.id=0; 
user.nickname="Pony"; 
user.***="?"; 
user.age=20; 
user.address="192.168.7.91"; 
user.password="123456"; 
bf.Serialize(stream,user); 
byte[] buff = stream.ToArray(); 
s.Send(buff,buff.Length,0); 
s.Close(); 
Console.WriteLine("?????!"); 


一下是client端接收到數(shù)據(jù)后反序列化 
BinaryFormatter bf; 
bf = new BinaryFormatter(); 
USER_INF user=(USER_INF)bf.Deserialize(s);

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,,所有內(nèi)容均由用戶發(fā)布,,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式,、誘導(dǎo)購買等信息,,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,,請(qǐng)點(diǎn)擊一鍵舉報(bào),。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多