LinuxSir.cn,穿越时空的Linuxsir!

 找回密码
 注册
搜索
热搜: shell linux mysql
查看: 2743|回复: 4

socket服务端如何连续接收客户端发来的数据?

[复制链接]
发表于 2005-3-28 22:54:20 | 显示全部楼层 |阅读模式
我写了socket服务端以及客户端程序,因是demo,一切errorcheck都省了!

  1. /*
  2. ** srvdemo.c - a stream socket server demo
  3. */
  4. #include <stdio.h>
  5. #include <string.h>
  6. #include <sys/types.h>
  7. #include <sys/socket.h>
  8. #include <arpa/inet.h>

  9. #define PORT 1234   
  10. #define BACKLOG 10   

  11. int main(void)
  12. {
  13.   int sockfd, new_fd;
  14.   struct sockaddr_in my_addr;   
  15.   struct sockaddr_in their_addr;
  16.   int sin_size;
  17.   char buf[15];

  18.   sockfd = socket(AF_INET, SOCK_STREAM, 0);

  19.   my_addr.sin_family = AF_INET;        
  20.   my_addr.sin_port = htons(PORT);   
  21.   my_addr.sin_addr.s_addr = INADDR_ANY;

  22.   memset(&(my_addr.sin_zero), '\0', 8);

  23.   bind(sockfd, (struct sockaddr *)&my_addr,
  24.        sizeof(struct sockaddr));

  25.   listen(sockfd, BACKLOG);

  26.   while(1)
  27.     {
  28.     sin_size = sizeof(struct sockaddr_in);
  29.    
  30.     new_fd = accept(sockfd, (struct sockaddr *)&their_addr,
  31.                          &sin_size);

  32.     printf("server: got connection from %s\n",
  33.            inet_ntoa(their_addr.sin_addr));

  34.     recv(new_fd, buf, 11, 0);
  35.     printf("server: %s\n", buf);
  36.     }
  37.   return 0;
  38. }
复制代码

这应该是一个典型的socket服务端程序。
下面是客户端demo。

  1. /*
  2. ** clientdemo.c - a stream socket client demo
  3. */
  4. #include <stdio.h>
  5. #include <unistd.h>
  6. #include <string.h>
  7. #include <netdb.h>
  8. #include <sys/types.h>
  9. #include <sys/socket.h>

  10. #define PORT 1234
  11. #define MAXDATASIZE 100

  12. int main(int argc, char *argv[])
  13. {
  14.   int sockfd, numbytes;
  15.   char buf[MAXDATASIZE];
  16.   struct hostent *he;
  17.   struct sockaddr_in their_addr;

  18.   he = gethostbyname(argv[1]);

  19.   sockfd = socket(AF_INET, SOCK_STREAM, 0);

  20.   their_addr.sin_family = AF_INET;   
  21.   their_addr.sin_port = htons(PORT);
  22.   their_addr.sin_addr = *((struct in_addr *)he->h_addr);

  23.   memset(&(their_addr.sin_zero), '\0', 8);

  24.   connect(sockfd, (struct sockaddr *)&their_addr,
  25.               sizeof(struct sockaddr));

  26.   sprintf(buf, "Hello,World");

  27.   send(sockfd, buf, 11, 0);
  28.   send(sockfd, buf, 5, 0);
  29.   close(sockfd);
  30.   return 0;
  31. }
复制代码

编译测试如下:
gcc -Wall srvdemo.c -o srvdemo
gcc -Wall clientdemo.c -o clientdemo

在一个终端输入启动srvdemo。在另一个终端运行客户端clientdemo localhost,结果如下
server: got connection from 127.0.0.1
server: Hello,World

我的问题是:我在客户端连续发送了两次数据,为什么服务端却只接收了一次呢?
如果我要服务端连续两次都接收到,要怎么样做?
发表于 2005-3-29 08:30:23 | 显示全部楼层
这是一个典型的问题程序

(1)第二次循环 accept 阻塞了,当然不会再收到 “hello world”,除非你再运行 client;

(2)如果把 accept 改对了,recv 不检查返回值,当客户端不再发送时,服务器仍会不停的打出 buf 内容。
回复 支持 反对

使用道具 举报

 楼主| 发表于 2005-3-29 08:41:41 | 显示全部楼层
我初学socket编程,还望大哥们多多指点。
这些细节问题,我还没仔细测试过。因为临时写的,比较随便。
但是主要是为了要有一个思路。
可是大哥还是没有给出提示,关于如何解决这个问题呀?
阻塞掉了,我也想是,可是如何觉解决呢?
回复 支持 反对

使用道具 举报

发表于 2005-3-29 09:08:43 | 显示全部楼层
socket 编程推荐看 《用TCP/IP实现网际互连,第三卷》和《UNIX网络编程》。

写代码之前先理清思路,服务器可以是循环的(非并发的)或者并发的,非并发服务器要求一次服务在较短时间内结束,否则会使其它客户端无法连接;并发服务器可以是多路IO的、多线程的、或者多进程的。

如果你是要实现一个非并发服务器。你的服务器程序中的 while 是要循环接受多个客户端的连接,接受连接以后,对每个客户端,你要接收若干数据,对于TCP协议而言,这些数据要 recv 多少次是不一定的,于是你要循环地 recv,并在每次 recv 后判断是否需要退出循环。

如果你要实现一个并发服务器,你需要(1)用 select 来管理 accept 及与各个客户端的数据收发;或者(2)在 accept 后为新连接建立一个线程或进程。当然,对每个连接,你还是要循环的 recv。

一定要理解 accept 和 recv 是对不同的 socket_fd,把这两个任务线性地放在同一个循环中,有概念不清之嫌。

如果不考虑错误处理,可以把 recv 那一句改成,while (recv(new_fd, buf, 11, 0) > 0) printf("server: %s\n", buf);
回复 支持 反对

使用道具 举报

 楼主| 发表于 2005-3-29 10:13:50 | 显示全部楼层
谢谢大哥的指点,我现在明白了一些问题。
首先,我知道我需要一个非并发的服务器。而且打算采用多线程。
我看我的问题就在于没有想到循环接收。
关于accept 和 recv 是对不同的 socket_fd,这个我是知道的。
最后多谢大哥!
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 返回顶部 返回列表