找回密碼 或 安全提問
 註冊
|註冊|登錄

伊莉討論區

搜索
請尊重及感激所有版主付出和奉獻尊貴會員無限使用任何功能你準備好成為出色的版主了嗎?
無修fc2cosplayge鬼父高中
3179154從lv2開yosino雷電將軍ドリス姫阿瓦隆大兄弟

休閒聊天興趣交流學術文化旅遊交流飲食交流家庭事務PC GAMETV GAME
熱門線上其他線上感情感性寵物交流家族門派動漫交流貼圖分享BL/GL
音樂世界影視娛樂女性頻道潮流資訊BT下載區GB下載區下載分享短片
電腦資訊數碼產品手機交流交易廣場網站事務長篇小說體育運動時事經濟
上班一族博彩娛樂

[繁]無職轉生 第二季1

[繁]從Lv2開始開外掛

[簡]Unnamed Memory

[繁]迷宮飯18-

[繁]轉生貴族憑鑑定技

[簡]單人房、日照一般
C & C++ 語言C# 語言Visual Basic 語言PHP 語言JAVA 語言
查看: 1199|回復: 14
打印上一主題下一主題

[問題]socket programming[複製鏈接]

  尊貴會員

Melty Snow  雪靈

Rank: 6Rank: 6Rank: 6Rank: 6Rank: 6Rank: 6

帖子
3222
積分
24364 點
潛水值
77260 米
跳轉到指定樓層
樓主
發表於 2013-11-23 05:31 PM|只看該作者|倒序瀏覽
本帖最後由 snowflying 於 2013-11-23 07:38 PM 編輯

最近在寫 socket programming 的部分,遇到了一些問題
先附上兩份 code (server 與 client)

server :
  1. //server
  2. #include <iostream>
  3. #include <cstdio>
  4. #include <cstdlib>
  5. #include <cstring>
  6. #include <unistd.h>
  7. #include <sys/types.h>
  8. #include <sys/socket.h>
  9. #include <arpa/inet.h>
  10. #include <netdb.h>
  11. #include <netinet/in.h>
  12. #define PORT 2727
  13. using namespace std;


  14. int listenfd , clifd;
  15. sockaddr_in servaddr , cliaddr;

  16. int main(int argc , char *argv[])
  17. {
  18.     listenfd = socket(AF_INET , SOCK_STREAM , 0);

  19.     memset(&servaddr , 0 , sizeof(servaddr));   

  20.     servaddr.sin_family = AF_INET;
  21.     servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
  22.     servaddr.sin_port = htons(PORT);

  23.     int sopt = 1;
  24.     setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, (void*)&sopt, sizeof(sopt));

  25.     bind(listenfd , (sockaddr *) &servaddr , sizeof(servaddr));

  26.     listen(listenfd , 100);

  27.     while(true)
  28.     {
  29.         socklen_t clilen = sizeof(cliaddr);

  30.         clifd = accept(listenfd , (sockaddr*) &cliaddr , &clilen);

  31.             
  32.         send(clifd , "XDDD\n" , strlen("XDDD\n") + 1 , 0);
  33.         //sleep(2);
  34.         send(clifd , "XDDD2\n" , strlen("XDDD2\n") + 1 , 0);
  35.         //sleep(2);
  36.         send(clifd , "XDDD3\n" , strlen("XDDD3\n") + 1 , 0);
  37.         //sleep(2);
  38.         
  39.         close(clifd);
  40.     }

  41.     return 0;
  42. }
複製代碼





client :
  1. //client
  2. #include <iostream>
  3. #include <cstdio>
  4. #include <cstdlib>
  5. #include <cstring>
  6. #include <unistd.h>
  7. #include <sys/types.h>
  8. #include <sys/socket.h>
  9. #include <arpa/inet.h>
  10. #include <netdb.h>
  11. #include <netinet/in.h>
  12. #define BUF_LEN 1000
  13. using namespace std;

  14. int main(int argc , char *argv[])
  15. {
  16.     if(argc < 3)
  17.         exit(1);

  18.     int servfd;
  19.     sockaddr_in servaddr;
  20.     in_addr ia;

  21.     memset(&servaddr , 0 , sizeof(servaddr));

  22.     servfd = socket(AF_INET , SOCK_STREAM , 0);

  23.     servaddr.sin_family = AF_INET;
  24.     inet_aton(argv[1] , &ia);
  25.     servaddr.sin_addr = ia;
  26.     servaddr.sin_port = htons(atoi(argv[2]));

  27.     if(connect(servfd , (sockaddr*) &servaddr , (socklen_t) sizeof(servaddr)) < 0)
  28.         exit(1);
  29.    
  30.     char sendline[BUF_LEN] , recvline[BUF_LEN];


  31.     while(true)
  32.     {
  33.         memset(recvline , 0 , sizeof(recvline));

  34.         read(servfd , recvline , BUF_LEN );
  35.         print f("%s\n" , recvline);
  36.         fflush(stdout);
  37.         sleep(4);

  38.         read(servfd , recvline , BUF_LEN );
  39.         print f("%s\n" , recvline);
  40.         fflush(stdout);
  41.         sleep(4);

  42.         read(servfd , recvline , BUF_LEN );
  43.         print f("%s\n" , recvline);
  44.         fflush(stdout);
  45.         sleep(4);

  46.         close(servfd);
  47.         break;
  48.     }

  49.     return 0;
  50. }
複製代碼



這兩份 code 是大略簡化過的,原本是還有 select 等
不過經過測試後,覺得問題應該是出在這個地方
依照上面兩份 code 執行結果 (ubuntu or BSD)
client 拿到的全為 "XDDD"

但是

1. 使用 telnet  (即不使用此 client 程式) ,拿到結果為正確的 ("XDDD" 、 "XDDD2" 、 "XDDD3")
2. 若把 server 的 code 中 sleep(2) 的註解全拿掉,使用此 client 程式,所拿到的結果也會是正確的

不知道是否有哪裡沒處理好,需要新增或修改的地方
也想了解直接藉由 telnet 與此 client 有何差異,為何可以拿到正確的結果
還請版上各位指點一下,感謝!

...
瀏覽完整內容,請先 註冊登入會員
分享分享0收藏收藏0支持支持0
Melty Snow [雪靈]
如果瀏覽伊莉時速度太慢或無法連接,可以使用其他分流瀏覽伊莉,www01.eyny.com(02,03)。

使用道具檢舉

Rank: 4Rank: 4Rank: 4Rank: 4

帖子
7565
積分
4321 點
潛水值
34960 米
頭香
發表於 2013-11-23 09:24 PM|只看該作者
本帖最後由 chevylin0802 於 2013-11-23 09:40 PM 編輯

server在沒有sleep的時候
會一次把三筆
依順序送到核心的緩衝區裏
所以你就只有接收到最前面的數據(但事實上接收到的長度是三個send個總合, 20)
而有sleep的時候
就會分批送
因此就正常

會有這種狀況的主因
是因為server端尚未把資料送出
就立即有新的資料需要傳送
...
瀏覽完整內容,請先 註冊登入會員
系統已重置禁訪用戶到普通用戶和密碼一次
分享使你變得更實在,可以使其他人感到快樂,分享是我們的動力。今天就來分享你的資訊、圖片或檔案吧。

使用道具檢舉

  尊貴會員

Melty Snow  雪靈

Rank: 6Rank: 6Rank: 6Rank: 6Rank: 6Rank: 6

帖子
3222
積分
24364 點
潛水值
77260 米
3
發表於 2013-11-23 10:16 PM|只看該作者
本帖最後由 snowflying 於 2013-11-23 10:18 PM 編輯
chevylin0802 發表於 2013-11-23 09:24 PM
下載: 訪客無法瀏覽下載點,請先 註冊登入會員

server在沒有sleep的時候
會一次把三筆
依順序送到核心的緩衝區裏
...
瀏覽完整內容,請先 註冊登入會員
Melty Snow [雪靈]
所有積分大於負-100的壞孩子,將可獲得重新機會成為懲罰生,權限跟幼兒生一樣。

使用道具檢舉

Rank: 4Rank: 4Rank: 4Rank: 4

帖子
7565
積分
4321 點
潛水值
34960 米
4
發表於 2013-11-23 10:50 PM|只看該作者
若新密碼無法使用,可能是數據未更新。請使用舊密碼看看。
snowflying 發表於 2013-11-23 10:16 PM
下載: 訪客無法瀏覽下載點,請先 註冊登入會員

檢測 read 回傳值,發現確實為 20

而剛以 usleep(1000) 測試

其實你的程式我看了也是覺得有點奇怪

一般我們在寫這種socket的程式
...
瀏覽完整內容,請先 註冊登入會員
系統已重置禁訪用戶到普通用戶和密碼一次
分享使你變得更實在,可以使其他人感到快樂,分享是我們的動力。今天就來分享你的資訊、圖片或檔案吧。

使用道具檢舉

  尊貴會員

Melty Snow  雪靈

Rank: 6Rank: 6Rank: 6Rank: 6Rank: 6Rank: 6

帖子
3222
積分
24364 點
潛水值
77260 米
5
發表於 2013-11-23 11:13 PM|只看該作者
chevylin0802 發表於 2013-11-23 10:50 PM
下載: 訪客無法瀏覽下載點,請先 註冊登入會員

其實你的程式我看了也是覺得有點奇怪

一般我們在寫這種socket的程式

其實我原本是用  read/write 來處理
...
瀏覽完整內容,請先 註冊登入會員





Melty Snow [雪靈]
回覆中加入附件並不會使你增加積分,請使用主題方式發佈附件。

使用道具檢舉

Rank: 4Rank: 4Rank: 4Rank: 4

帖子
7565
積分
4321 點
潛水值
34960 米
6
發表於 2013-11-24 01:09 AM|只看該作者
成為伊莉的版主,你將獲得更高級和無限的權限。把你感興趣的版面一步步地發展和豐盛,那種滿足感等著你來嚐嚐喔。
本帖最後由 chevylin0802 於 2013-11-24 01:13 AM 編輯
snowflying 發表於 2013-11-23 11:13 PM
下載: 訪客無法瀏覽下載點,請先 註冊登入會員

其實我原本是用  read/write 來處理
在測試的時候,想說不知道是不是 write() 出錯,改以 send() 處理
cl ...
...
瀏覽完整內容,請先 註冊登入會員
系統已重置禁訪用戶到普通用戶和密碼一次
若對尊貴或贊助會員有任何疑問,歡迎向我們查詢。我們的即時通或MSN: admin@eyny.com

使用道具檢舉

帖子
16
積分
15 點
潛水值
2124 米
7
發表於 2013-11-24 06:08 PM|只看該作者
所有積分大於負-100的壞孩子,將可獲得重新機會成為懲罰生,權限跟幼兒生一樣。
建議幫你的封包定義一個格式,也就是除了原本的字串以外,另外加上header,最簡單的header應該要有封包型態,封包長度。client可以藉由讀取header來判斷是否已經收到一個完整的封包。
因為你不能保證每次client呼叫read都會得到完整的字串,所以client一定要檢查read的回傳值來判斷是否有收到任何東西(或是否有錯誤發生)

你的case的話,client的while loop裡面只需要一個read(or recv),直到收到完整的封包才print,之前每次有收到任何東西,只需要寫進buffer,然後進入下一個迴圈即可...
瀏覽完整內容,請先 註冊登入會員

使用道具檢舉

Rank: 4Rank: 4Rank: 4Rank: 4

帖子
7565
積分
4321 點
潛水值
34960 米
8
發表於 2013-11-24 08:22 PM|只看該作者
本帖最後由 chevylin0802 於 2013-11-24 08:23 PM 編輯
akpete2 發表於 2013-11-24 06:08 PM
下載: 訪客無法瀏覽下載點,請先 註冊登入會員

建議幫你的封包定義一個格式,也就是除了原本的字串以外,另外加上header,最簡單的header應該要有封包型態 ...
...
瀏覽完整內容,請先 註冊登入會員
系統已重置禁訪用戶到普通用戶和密碼一次

使用道具檢舉

帖子
16
積分
15 點
潛水值
2124 米
9
發表於 2013-11-25 01:07 PM|只看該作者
分享使你變得更實在,可以使其他人感到快樂,分享是我們的動力。今天就來分享你的資訊、圖片或檔案吧。
chevylin0802 發表於 2013-11-24 08:22 PM
下載: 訪客無法瀏覽下載點,請先 註冊登入會員

他的狀況是
三次send被一次read讀出
跟有沒有完整的定義protocol封包是無關的事情

我指的是user自己定義的protocol,這是定義在user space的,跟TCP,UDP,checksum error那些都沒有關係。
...
瀏覽完整內容,請先 註冊登入會員
若新密碼無法使用,可能是數據未更新。請使用舊密碼看看。

使用道具檢舉

Rank: 4Rank: 4Rank: 4Rank: 4

帖子
7565
積分
4321 點
潛水值
34960 米
10
發表於 2013-11-25 01:34 PM|只看該作者
akpete2 發表於 2013-11-25 01:07 PM
下載: 訪客無法瀏覽下載點,請先 註冊登入會員

我指的是user自己定義的protocol,這是定義在user space的,跟TCP,UDP,checksum error那些都沒有關係。 ...

UDP的情形不一樣
UDP有分multicast與unicast的情形
...
瀏覽完整內容,請先 註冊登入會員





系統已重置禁訪用戶到普通用戶和密碼一次
若對尊貴或贊助會員有任何疑問,歡迎向我們查詢。我們的即時通或MSN: admin@eyny.com

使用道具檢舉

weema 該用戶已被刪除
11
發表於 2013-11-25 10:19 PM|只看該作者
如果每個封包不定長度,我比較認同 akpete2 的做法

發送端 ======================================
char *buf = "XDDD\n";
int len = strlen(buf);

send(sd, &len, sizeof(int)); // 送出長度
send(sd, buf, len);     // 送出資料

接收端 ======================================
int len;
char buf[256];

recv(sd, &len, sizeof(int)); // 讀出長度
recv(sd, buf, len);      // 讀出資料
...
瀏覽完整內容,請先 註冊登入會員

點評

snowflying 其實只要不要連 '\0' 一起送出沒問題了 (指輸出部分),存入 buffer 後,檢查下一位是否為 '\0' 就是了  發表於 2013-11-25 10:29 PM
如果你忘記伊莉的密碼,請在登入時按右邊出現的 '找回密碼'。輸入相關資料後送出,系統就會把密碼寄到你的E-Mail。

使用道具檢舉

Rank: 4Rank: 4Rank: 4Rank: 4

帖子
7565
積分
4321 點
潛水值
34960 米
12
發表於 2013-11-26 09:19 AM|只看該作者
如果瀏覽伊莉時速度太慢或無法連接,可以使用其他分流瀏覽伊莉,www01.eyny.com(02,03)。
本帖最後由 chevylin0802 於 2013-11-26 09:33 AM 編輯
snowflying 發表於 2013-11-23 11:13 PM
下載: 訪客無法瀏覽下載點,請先 註冊登入會員

其實我原本是用  read/write 來處理
在測試的時候,想說不知道是不是 write() 出錯,改以 send() 處理
cl ...
...
瀏覽完整內容,請先 註冊登入會員
系統已重置禁訪用戶到普通用戶和密碼一次
回覆中加入附件並不會使你增加積分,請使用主題方式發佈附件。

使用道具檢舉

帖子
16
積分
15 點
潛水值
2124 米
13
發表於 2013-11-27 03:28 PM|只看該作者
chevylin0802 發表於 2013-11-26 09:19 AM
下載: 訪客無法瀏覽下載點,請先 註冊登入會員

protocol這種東西
不是只有ethernet或wifi才有的

你扯太遠了
我當然知道不一定需要封包長度也可以
以他的例子,封包裡是字串,可以以換行字元來分封包沒問題
...
瀏覽完整內容,請先 註冊登入會員
如果瀏覽伊莉時速度太慢或無法連接,可以使用其他分流瀏覽伊莉,www01.eyny.com(02,03)。

使用道具檢舉

Rank: 4Rank: 4Rank: 4Rank: 4

帖子
7565
積分
4321 點
潛水值
34960 米
14
發表於 2013-11-27 04:04 PM|只看該作者
如果發覺自己無法使用一些功能或出現問題,請按重新整理一次,並待所有網頁內容完全載入後5秒才進行操作。
akpete2 發表於 2013-11-27 03:28 PM
下載: 訪客無法瀏覽下載點,請先 註冊登入會員

你扯太遠了
我當然知道不一定需要封包長度也可以
以他的例子,封包裡是字串,可以以換行字元來分封包沒問 ...

...
瀏覽完整內容,請先 註冊登入會員
系統已重置禁訪用戶到普通用戶和密碼一次
若對尊貴或贊助會員有任何疑問,歡迎向我們查詢。我們的即時通或MSN: admin@eyny.com

使用道具檢舉

  尊貴會員

Melty Snow  雪靈

Rank: 6Rank: 6Rank: 6Rank: 6Rank: 6Rank: 6

帖子
3222
積分
24364 點
潛水值
77260 米
15
發表於 2013-11-28 11:55 PM|只看該作者
如果瀏覽伊莉時速度太慢或無法連接,可以使用其他分流瀏覽伊莉,www01.eyny.com(02,03)。
先感謝幾位前輩的回覆
原先的問題確實是在於 "三次的send 一次全讀到/接收到"
後來的確是有問到  "一般對於這種情況該如何處理"
是想比較各種方法的差異,和自身所用的方法是法有何優劣
所以兩位提到的方法在目前所遇到的問題,是都可以做為解決方法
有敘述不太詳盡的地方還請見諒
也感謝各位的解說~!




Melty Snow [雪靈]
分享使你變得更實在,可以使其他人感到快樂,分享是我們的動力。今天就來分享你的資訊、圖片或檔案吧。

使用道具檢舉

您需要登錄後才可以回帖 登錄 | 註冊

Powered by Discuz!

© Comsenz Inc.

重要聲明:本討論區是以即時上載留言的方式運作,對所有留言的真實性、完整性及立場等,不負任何法律責任。而一切留言之言論只代表留言者個人意見,並非本網站之立場,用戶不應信賴內容,並應自行判斷內容之真實性。於有關情形下,用戶應尋求專業意見(如涉及醫療、法律或投資等問題)。 由於本討論區受到「即時上載留言」運作方式所規限,故不能完全監察所有留言,若讀者發現有留言出現問題,請聯絡我們。有權刪除任何留言及拒絕任何人士上載留言,同時亦有不刪除留言的權利。切勿上傳和撰寫 侵犯版權(未經授權)、粗言穢語、誹謗、渲染色情暴力或人身攻擊的言論,敬請自律。本網站保留一切法律權利。
回頂部