Socket中send方法傳送結構體和recv接受結構體
Socket中的send函式可以傳送字串,但不能直接傳送結構體,因此在傳送端先把結構體轉成字串,然後用send傳送,在接收端recv字串,再轉換成原先的結構體,這個就是解決問題的主要思路,實現中要注意的問題在下文闡述。
為了客戶端之間能夠互相通訊,實現私聊,我採用伺服器轉發的方式,因此使用者傳送的每條訊息中除了訊息主體外,還必須包含有傳送者、接收者ID等資訊,如此採用結構體便是最佳的辦法了。我定義的結構體如下:
1 2 3 4 5 6 7 | struct send_info { char info_from[20]; //傳送者ID char info_to[20]; //接收者ID int info_length; //傳送的訊息主體的長度 char info_content[1024]; //訊息主體 }; |
傳送端主要程式碼(為了簡潔說明問題,我把使用者輸入的內容、長度等驗證的程式碼去掉了):
1 2 3 4 5 6 7 8 9 10 11 | struct send_info info1; //定義結構體變數 printf("This is client,please input message:"); //從鍵盤讀取使用者輸入的資料,並寫入info1.info_content memset(info1.info_content,0,sizeof(info1.info_content));//清空快取 info1.info_length=read(STDIN_FILENO,info1.info_content,1024) - 1;//讀取使用者輸入的資料 memset(snd_buf,0,1024);//清空傳送快取,不清空的話可能導致接收時產生亂碼, //或者如果本次傳送的內容少於上次的話,snd_buf中會包含有上次的內容 memcpy(snd_buf,&info1,sizeof(info1)); //結構體轉換成字串 send(connect_fd,snd_buf,sizeof(snd_buf),0);//傳送資訊 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | struct send_info clt; //定義結構體變數 memset(recv_buf,'z',1024);//清空快取 recv(fd,recv_buf,1024,0 );//讀取資料 memset(&clt,0,sizeof(clt));//清空結構體 memcpy(&clt,recv_buf,sizeof(clt));//把接收到的資訊轉換成結構體 clt.info_content[clt.info_length]=''; //訊息內容結束,沒有這句的話,可能導致訊息亂碼或輸出異常 //有網友建議說傳遞的結構體中儘量不要有string型別的欄位,估計就是串尾符定位的問題 if(clt.info_content) //判斷接收內容並輸出 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); //至此,結構體的傳送與接收已經順利結束了 |
c/c++通過socket傳送結構可以直接先將結構轉化到記憶體中,再通過send直接傳送。
在網路通訊過程中往往涉及一些有關聯的引數傳遞,例如陣列,結構體之類的。對於結構體其實方法挺簡單,由於結構體物件在記憶體中分配的空間都是連續的,所以可以將整個結構體直接轉化成字串傳送,到了接收方再將這個字串還原成結構體就大功告成了。
首先,我們建立一個結構體。
struct UsrData{
char usr_id[16];
char usr_pwd[16];
char usr_nickname[16];
};
當然,這個結構體在傳送方與接收方都必須宣告。
接下來建立物件並初始化,然後傳送。
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 );
這樣傳送方就已經將這個mUser物件以字串的形式傳送出去了。
最後在接收方做接收。
char buffer[1024];
UsrData recvUser;
recv( m_socket, buffer, sizeof(buffer), 0 );
memcpy( &recvUser, buffer, sizeof(buffer) );
這樣得到的recvUser物件裡的資料與sendUser相同了。具體原因其實很簡單,就是因為結構體物件的記憶體區域連續,同時每個成員的區塊大小都分配好了,當接收完自己的區塊,其實自己的資料已經接收完成。挺簡單的,但還是挺有用的。
也可以直接將記憶體寫到檔案中:
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是自定義的結構
close(cfg_fd);
printf("the para which is written to the config file:/n");
read(cfg_fd, &hd4100_config, sizeof(hd4100_rec_t)); //從檔案讀內容到記憶體中
close(cfg_fd);
包含引用型別或值型別的結構或物件無法通過以上方法直接傳送,而必須通過序列化的方式轉化為二進位制流傳送和接收。如c# Socket傳送序列化Struct示例:
傳資料,下面給一個傳送struct的例子.
首先:把struct寫到一個單獨的類中.編譯成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;
}
然後在你的伺服器端和客戶端都新增這個dll.
下面是伺服器端傳送這個序列化的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端接收到資料後反序列化
BinaryFormatter bf;
bf = new BinaryFormatter();
USER_INF user=(USER_INF)bf.Deserialize(s);
相關推薦
Socket中send方法傳送結構體和recv接受結構體
Socket中的send函式可以傳送字串,但不能直接傳送結構體,因此在傳送端先把結構體轉成字串,然後用send傳送,在接收端recv字串,再轉換成原先的結構體,這個就是解決問題的主要思路,實現中要注意的問題在下文闡述。 為了客戶端之間能夠互相通訊,實現私聊
SOCKET中send和recv函式工作原理與注意點
send函式工作原理: send函式只負責將資料提交給協議層。 當呼叫該函式時,send先比較待發送資料的長度len和套接字s的傳送緩衝區的長度,如果len大於s的傳送緩衝區的長度,該函式返回SO
socket中send和recv函式的阻塞理解
int send( SOCKET s, const char FAR *buf, int len, int flags ); 不論是客戶還是伺服器應用程式都用send函式來向TCP連線的另一端傳送資料。客戶程式一般用send函式向伺服器傳送請求,而伺服器則通常用send函式來向客戶程式傳送應答。 該函式的
Socket中send()函式和recv()函式詳解
1、send函式 int send( SOCKET s, const char FAR *buf, int len, int flags ); 不論是客戶還是伺服器應用程式都用send函式來向TCP連線的另一端傳送資料。 客戶程式一般用send函式向伺服器傳送請求,而伺
很簡單的在Ubuntu系統下安裝字體和切換默認字體的方法
拷貝 true 桌面 技術 系統 美麗 des net 加粗 摘要: Ubuntu系統安裝好後,默認字體對於中文的支持看上去不太美麗,於是很多朋友可能需要設置系統的默認字體為自己喜歡的字體。本文主要介紹如何解決這兩個問題。 說明:測試系統是Ubuntu14.04。
資料結構---棧和佇列(結構體實現)
棧(LIFO) 棧(stack)是一種只能在一端進行插入或刪除操作的線性表。 棧頂(top):允許進行插入、刪除操作的一端 棧底(bottom):另一端稱為棧底 進棧或入棧(push):插入操作 出棧或退棧(pop):棧的刪除操作 n個不同元素通過一個棧產生的出棧
spring框架中工廠方法的創建和銷毀
color this alt ima 實現 close col out err 1.編寫接口UserSerivce: public interface UserService { public void sayHello(); } 2.編寫實實現接口的方法,在
Android-LayoutInflater中inflate方法兩個引數和三個引數的區別
關於inflate引數問題,我想很多人多多少少都瞭解一點,網上也有很多關於這方面介紹的文章,但是枯燥的理論或者翻譯讓很多小夥伴看完之後還是一臉懵逼,so,我今天想通過三個案例來讓小夥伴徹底的搞清楚這個東東。本篇部落格我們不講原始碼,只看使用。原始碼的解讀會在下一篇博文中帶
三個案例帶你看懂LayoutInflater中inflate方法兩個引數和三個引數的區別
關於inflate引數問題,我想很多人多多少少都瞭解一點,網上也有很多關於這方面介紹的文章,但是枯燥的理論或者翻譯讓很多小夥伴看完之後還是一臉懵逼,so,我今天想通過三個案例來讓小夥伴徹底的搞清楚這個東東。本篇部落格我們不講原始碼,只看使用。原始碼的解讀會在下一篇博文中帶來。
socket之send與傳送緩衝區大小的關係
自己做了個測試,伺服器只起socket在偵聽,不recv, 也不send. //ubuntu10.04 32bit #include <stdio.h> #include <sys/types.h> #include <sys/socke
jquery中.on()方法指定子元素和不指定子元素的區別
首先來看下這兩種情況下的輸出: <div class="parent"> <div class="father"> <div class="son">測試.on()方法</div>
Java中clone方法以及深複製和淺複製
Java中處理基本資料型別(如:int , char , double等),都是採用按值傳遞的方式執行,除此之外的其他型別都是按照引用傳遞(傳遞的是一個物件的引用)的方式執行。物件在函式呼叫時和使用“=”賦值時都是引用傳遞。 Java中clone方法的作用是為了在現實程式
jq中each方法的退出迴圈和結束本次迴圈
Query中each類似於javascript的for迴圈 但不同於for迴圈的是在each裡面不能使用break結束迴圈,也不能使用continue來結束本次迴圈,想要實現類似的功能就只能用return,break 用return falsecontin
路由器刷opwenwrt韌體和原廠韌體教程
本文所用的路由器型號為:linksys wrt1900ac v2(第一次寫部落格,竟然發現CSDN的部落格不能快速插入圖片,差評) 環境準備 網線插入路由器的網線介面,然後再由路由器的LAN介面
H264碼流結構分析和rtp打包結構詳解
網路抽象層單元型別 (NALU): NALU頭由一個位元組組成,它的語法如下: +---------------+ |0|1|2|3|4|5|6|7| +-+-+-+-+-+-+-+-+ |F|NRI| Type | +---------
C語言中結構體以及在結構體中呼叫方法;聯合體和聯合體的使用
#include <stdio.h> #include<stdlib.h>void study(){}; struct student{ int age; int number; void(*study1)(); } main(){//使用,在結構
淺談c++中結構體和共用體的區別
ont 基本類型 erl list 變量名 ext 使用結構體 oot 數據格式 在c++中,結構體(struct)和共用體(union)是兩種很相似的復合數據類型,都可以用來存儲多種數據類型,但是兩者還有很大的區別。 結構體(struct) 結構是用戶自定
結構體和方法
pan att div println sel res bug com .com 結構體和方法 use std::fmt; #[derive(Debug)] struct Rectangle { width: u32, height: u32, }
C#將結構體和指針互轉的方法
緩沖 style system RR 程序集 ascii 通知 work Coding 1. 功能及位置 將數據從托管對象封送到非托管內存塊,屬於.NET Framework 類庫 命名空間:System.Runtime.InteropServices
結構體和連結串列中陣列和指標不同表達形式
int getMaxLengthOfItems(MEC_MENU *menu,int count){ int i; int maxLen = strlen(menu[0].item); for(i = 0; i < c