亚洲av成人无遮挡网站在线观看,少妇性bbb搡bbb爽爽爽,亚洲av日韩精品久久久久久,兔费看少妇性l交大片免费,无码少妇一区二区三区

  免費注冊 查看新帖 |

Chinaunix

  平臺 論壇 博客 文庫
12下一頁
最近訪問板塊 發(fā)新帖
查看: 8865 | 回復: 17
打印 上一主題 下一主題

[C] linux socket接收未知長度的字符串問題 [復制鏈接]

論壇徽章:
0
跳轉(zhuǎn)到指定樓層
1 [收藏(0)] [報告]
發(fā)表于 2013-07-18 11:20 |只看該作者 |倒序瀏覽
情景:客戶端通過socket向服務(wù)器發(fā)送 開始標志0x02+命令+數(shù)據(jù) +結(jié)束標志0x03
例如:2NEW|20130716001|M3
主要問題是:客戶端發(fā)送的數(shù)據(jù)長度是未知的,我現(xiàn)在的程序一次能接收的數(shù)據(jù)長度是定義好的,比如512,1024。我想做到結(jié)束不定長度的數(shù)據(jù),檢測到結(jié)束標志0x03的時候才結(jié)束。

我現(xiàn)在的程序是阻塞的。請高手幫我看下,下面是我現(xiàn)在的程序,需要怎么修改才可以實現(xiàn)我說的功能,給個思路也可以。

main.c
  1. #include <stdio.h>
  2. #include <pthread.h>
  3. #include "socket.h"

  4. int main(int argc, char *argv[])
  5. {
  6.         pthread_t t;
  7.           pthread_create(&t,NULL,mysocket,NULL);   //socket
  8.          
  9.           while(1)
  10.           {}

  11.         return 0;
  12. }
復制代碼
socket.c
  1. #include "socket.h"
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include <string.h>
  5. #include <sys/socket.h>       /*  socket definitions        */
  6. #include <sys/types.h>        /*  socket types              */
  7. #include <arpa/inet.h>        /*  inet (3) funtions         */
  8. #include <unistd.h>           /*  misc. UNIX functions      */

  9. /*******************************************************
  10. *  函數(shù)名稱:mysocket
  11. *  參數(shù)列表:void* args
  12. *  返回值:  NULL
  13. *  函數(shù)功能:socket線程函數(shù)
  14. *******************************************************/
  15. void* mysocket(void* args)
  16. {
  17.              unsigned char buf[MAX_LINE];
  18.              unsigned char addr_p[INET_ADDRSTRLEN];
  19.              unsigned int  n,i,ret;

  20.         int       list_s;                /*  listening socket          */
  21.           int       conn_s;                /*  connection socket         */
  22.              socklen_t len;
  23.             short int port;                  /*  port number               */
  24.             struct    sockaddr_in servaddr;  /*  socket address structure  */
  25.         struct    sockaddr_in clenaddr;  /*  socket address structure  */
  26.         /*清空結(jié)構(gòu)體*/
  27.         memset(&servaddr,0,sizeof(servaddr));
  28.         /*  Set all bytes in socket address structure to
  29.                 zero, and fill in the relevant data members   */       
  30.         memset(&servaddr, 0, sizeof(servaddr));
  31.         servaddr.sin_family      = AF_INET;
  32.         servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
  33.         servaddr.sin_port        = htons(MYPORT);

  34.         /*  Create the listening socket  */
  35.         if ( (list_s = socket(AF_INET, SOCK_STREAM, 0)) < 0 ) {
  36.                 perror("create socket error:");
  37.         }
  38.         /*允許地址立即重用*/
  39.         unsigned int bReuseaddr =  0x01;
  40.         setsockopt(list_s,SOL_SOCKET,SO_REUSEADDR,(void *)&bReuseaddr,sizeof(bReuseaddr));
  41.         /*  Bind our socket addresss to the
  42.             listening socket, and call listen()  */
  43.              if( bind(list_s, (struct sockaddr *)&servaddr, sizeof(servaddr)) < 0) {
  44.                 perror("bind socket error:");
  45.         }

  46.         if ( listen(list_s, 10) < 0 ) {
  47.                 perror("listen socket error:");
  48.            }  
  49.              printf("waiting ...\n");

  50.         while(1)
  51.         {
  52.                 len = sizeof(struct sockaddr_in);
  53.                 /*  Wait for a connection, then accept() it  */
  54.                 conn_s = accept(list_s, (struct sockaddr *) &clenaddr, &len);
  55.                 if(conn_s < 0) {
  56.                         perror("accept socket error:");
  57.                 }

  58.                 memset( buf, '\0', MAX_LINE );
  59.                 n = read(conn_s, buf, MAX_LINE);

  60.                 inet_ntop(AF_INET, &clenaddr.sin_addr, addr_p, sizeof(addr_p));
  61.                 printf("client IP is %s, port is %d\n", addr_p, ntohs(servaddr.sin_port));

  62.                 printf("read n = %d \n",n);

  63.                 if(n == 0){
  64.                         printf("no message! \n");
  65.                         close(conn_s);
  66.                         break;
  67.                 }
  68.                 printf("%s\n",buf);

  69.                 close(conn_s);
  70.         }

  71.         if(close(list_s) == -1){
  72.                 perror("fail to close");
  73.                 exit(1);
  74.         }

  75.         return NULL;
  76. }
復制代碼
socket.h
  1. #ifndef _SOCKET_H
  2. #define _SOCKET_H

  3. #define MAX_LINE 8
  4. #define MYPORT 8000

  5. void* mysocket(void* args);

  6. #endif
復制代碼
一次接受的最大數(shù)據(jù)設(shè)為8 是為了測試方便。

客戶端:
client.c
  1. #include <stdio.h>
  2. #include <sys/socket.h>
  3. #include <arpa/inet.h>
  4. #include <string.h>
  5. #include <stdlib.h>

  6. #define DEST_IP "127.0.0.1"
  7. #define DEST_PORT 8000

  8. int main(int argc, char *argv[])
  9. {
  10.      struct sockaddr_in sin;
  11.      int sfd,n,i;
  12.      char *str = "1234567890";

  13.      bzero( &sin, sizeof( sin ) );
  14.      sin.sin_family = AF_INET;
  15.      sin.sin_addr.s_addr = inet_addr( DEST_IP );
  16.      sin.sin_port = htons( DEST_PORT );

  17.      sfd = socket( AF_INET, SOCK_STREAM, 0 );
  18.      connect( sfd, (struct sockaddr *)&sin, sizeof(sin));
  19.      write( sfd, str, strlen( str ) );

  20.      close(sfd);

  21.      return 0;
  22. }

復制代碼
客戶端發(fā)送這樣的數(shù)據(jù),服務(wù)器只能接收到“12345678”。

論壇徽章:
1
2015年辭舊歲徽章
日期:2015-03-03 16:54:15
2 [報告]
發(fā)表于 2013-07-18 13:01 |只看該作者
整個邏輯分成這麼幾層:網(wǎng)絡(luò)層只管收數(shù)據(jù)放到一塊內(nèi)存裏,然後協(xié)議解析層負責解析內(nèi)存裏的數(shù)據(jù)得到一個個的數(shù)據(jù)包,最後應(yīng)用層處理一個個的數(shù)據(jù)包就可一了。一般的二進制協(xié)議設(shè)計會在數(shù)據(jù)包開頭加入整個數(shù)據(jù)包的長度,這樣解析的時候讀完指定長度的數(shù)據(jù)就是一個包了。 文本協(xié)議可能就是樓主原來實現(xiàn)的這種靠特殊字符或者字符串來標誌數(shù)據(jù)包的結(jié)束。

論壇徽章:
0
3 [報告]
發(fā)表于 2013-07-18 13:57 |只看該作者
tcp本身是流式的,你盡可能地收,收到了之后,再從字符數(shù)組里找0x03,每找到一個,就提取出來。如果最后幾個字符沒找到,就把它們做為包頭,下一次再接收到數(shù)據(jù)后,把收到的數(shù)據(jù)附在之后就可以了。

論壇徽章:
0
4 [報告]
發(fā)表于 2013-07-18 14:53 |只看該作者
回復 2# csumck


    我看了很多網(wǎng)絡(luò)上的例子,包括使用select實現(xiàn)非阻塞模式的,都是有設(shè)定一次接收的最大字符數(shù)。

    我現(xiàn)在的代碼不是只read了一次么,我本來想寫一個循環(huán)去不斷的read,直到從接收的數(shù)據(jù)中找到0x03才結(jié)束read,重新等待。

    但是代碼沒有寫出來。在read的地方修改:

    while( buf[n-1] != 0x03 )       //判斷接收到的數(shù)據(jù)的最后一位
    {
            n = read(conn_s, buf, MAX_LINE);            //讀取客戶端數(shù)據(jù)
            strcat( savebuf, buf );             //將接收到的數(shù)據(jù)添加到savebuf中,這里也沒有辦法確定savebuf的大小,所以應(yīng)該根據(jù) n 的大小動態(tài)申請內(nèi)存
     }

     這段代碼不行的,是不是不能在while(1)中再嵌套while(1)啊

論壇徽章:
0
5 [報告]
發(fā)表于 2013-07-18 16:14 |只看該作者
while( buf[n-1] != 0x03 )
這有個前提,每次read,正好把發(fā)送的這一條全接下來,不多也不少。但上面說了,TCP是流式的,不可能實現(xiàn)的。UDP沒問題。
如果你while,也可以,每次讀一個字符:n = read(conn_s, buf, 1);  然后看這個字符是不是0x03。不要認為這樣慢, 很多輕量級的http server都是這么讀的。

如果一次讀多字符,就一直讀到n<=0,然后再回過去來處理字符串。這時savebuf里面肯定是有多個0x03,依次取,留下一點尾巴就是下一包的前半段。

論壇徽章:
1
2015年辭舊歲徽章
日期:2015-03-03 16:54:15
6 [報告]
發(fā)表于 2013-07-18 17:30 |只看該作者
回復 4# dolphin836


    給你寫個僞代碼:
while(讀取網(wǎng)絡(luò)數(shù)據(jù)到內(nèi)存buf中)//網(wǎng)絡(luò)層
{
     while(在buf中查找0x03)//協(xié)議解析層
     {
          將0x03之前的數(shù)據(jù)作爲數(shù)據(jù)包取出來處理; //應(yīng)用層
     }
}

論壇徽章:
4
水瓶座
日期:2013-09-06 12:27:30摩羯座
日期:2013-09-28 14:07:46處女座
日期:2013-10-24 14:25:01酉雞
日期:2014-04-07 11:54:15
7 [報告]
發(fā)表于 2013-07-18 17:30 |只看該作者
不夠長就先攢著啊.

論壇徽章:
0
8 [報告]
發(fā)表于 2013-07-18 22:12 |只看該作者
先分析一下客戶端發(fā)送數(shù)據(jù)的需求。
1.1為什么會出現(xiàn)不定長數(shù)據(jù)?
1.2 這些不定長數(shù)據(jù)的長度的統(tǒng)計信息--期望找到最大值

論壇徽章:
4
雙子座
日期:2014-08-28 10:08:002015年辭舊歲徽章
日期:2015-03-03 16:54:152015年迎新春徽章
日期:2015-03-04 09:58:112015年亞洲杯之阿聯(lián)酋
日期:2015-03-13 03:25:15
9 [報告]
發(fā)表于 2013-07-18 22:49 |只看該作者
思路不對,從來不要做一個接收未知長度的socket。

論壇徽章:
0
10 [報告]
發(fā)表于 2013-07-19 09:09 |只看該作者
這個程序是在一個病人信息管理系統(tǒng)中,例如鎖定病人,客戶端就要發(fā)送病人的studyid到服務(wù)器,但是一次選擇鎖定多少病人是不定的,
所以一次會發(fā)送的studyid個數(shù)也不定,所以數(shù)據(jù)包的長度也就不定了。我只收到了這樣的協(xié)議,至于修改協(xié)議會很麻煩,要開會。
你覺得這樣的協(xié)議合理么?是否存在弊端?是否需要設(shè)定最大允許的個數(shù)?還有就是,是否在數(shù)據(jù)包開始附加字符包長度更好?
回復 8# buzs


   
您需要登錄后才可以回帖 登錄 | 注冊

本版積分規(guī)則 發(fā)表回復

  

北京盛拓優(yōu)訊信息技術(shù)有限公司. 版權(quán)所有 京ICP備16024965號-6 北京市公安局海淀分局網(wǎng)監(jiān)中心備案編號:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年舉報專區(qū)
中國互聯(lián)網(wǎng)協(xié)會會員  聯(lián)系我們:huangweiwei@itpub.net
感謝所有關(guān)心和支持過ChinaUnix的朋友們 轉(zhuǎn)載本站內(nèi)容請注明原作者名及出處

清除 Cookies - ChinaUnix - Archiver - WAP - TOP