免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 1958 | 回复: 8
打印 上一主题 下一主题

请教TCP SOCKET 的问题 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2003-04-17 14:37 |只看该作者 |倒序浏览
我有两个程序,  一个服务器程序和一个客户程序. 服务器程序产生一个SOCKET , 和一个端口绑定.  然后不断检查是否有客户连接的到来. 当有客户连接到来就,  client_fd = accept (server_fd, .... )
然后不断读入客户程序写入的数据.  客户连接一旦建立,  就一直连接, 直到客户程序关断.  我现在的问题是服务器程序怎么才能知道客户程序关断了这个连接呢?  从而服务器程序close(client_fd )


谢谢

论坛徽章:
0
2 [报告]
发表于 2003-04-17 14:54 |只看该作者

请教TCP SOCKET 的问题

客户端close掉套接口的话会发送一个FIN给服务端,
服务端这时候从套接口read的话,会返回 0,表示对方已关闭套接口。

论坛徽章:
0
3 [报告]
发表于 2003-04-17 15:07 |只看该作者

请教TCP SOCKET 的问题

原帖由 "uiibono" 发表:
客户端close掉套接口的话会发送一个FIN给服务端,
服务端这时候从套接口read的话,会返回 0,表示对方已关闭套接口。


怎么检查FIN呢?  如果是客户端程序退出了呢?

论坛徽章:
1
荣誉版主
日期:2011-11-23 16:44:17
4 [报告]
发表于 2003-04-17 15:10 |只看该作者

请教TCP SOCKET 的问题

1、ssize_t write(int fd,const void *buf,size_t nbytes)

write函数将buf中的nbytes字节内容写入文件描述符fd.成功时返回写的字节数.失败时返回-1. 并设置errno变量. 在网络程序中,当我们向套接字文件描述符写时有俩种可能.

1)write的返回值大于0,表示写了部分或者是全部的数据.

2)返回的值小于0,此时出现了错误.我们要根据错误类型来处理.

如果错误为EINTR表示在写的时候出现了中断错误.

如果为EPIPE表示网络连接出现了问题(对方已经关闭了连接).

为了处理以上的情况,我们自己编写一个写函数来处理这几种情况.


  1. int my_write(int fd,void *buffer,int length)
  2. {
  3. int bytes_left;
  4. int written_bytes;
  5. char *ptr;

  6. ptr=buffer;
  7. bytes_left=length;
  8. while(bytes_left>;0)
  9. {
  10. /* 开始写*/
  11. written_bytes=write(fd,ptr,bytes_left);
  12. if(written_bytes<=0) /* 出错了*/
  13. {
  14. if(errno==EINTR) /* 中断错误 我们继续写*/
  15. written_bytes=0;
  16. else /* 其他错误 没有办法,只好撤退了*/
  17. return(-1);
  18. }
  19. bytes_left-=written_bytes;
  20. ptr+=written_bytes; /* 从剩下的地方继续写 */
  21. }
  22. return(0);
  23. }
复制代码

2、ssize_t read(int fd,void *buf,size_t nbyte) read函数是负责从fd中读取内容.当读成功时,read返回实际所读的字节数,如果返回的值是0 表示已经读到文件的结束了,小于0表示出现了错误.如果错误为EINTR说明读是由中断引起的, 如果是ECONNREST表示网络连接出了问题. 和上面一样,我们也写一个自己的读函数.


  1. int my_read(int fd,void *buffer,int length)
  2. {
  3. int bytes_left;
  4. int bytes_read;
  5. char *ptr;

  6. bytes_left=length;
  7. while(bytes_left>;0)
  8. {
  9. bytes_read=read(fd,ptr,bytes_read);
  10. if(bytes_read<0)
  11. {
  12. if(errno==EINTR)
  13. bytes_read=0;
  14. else
  15. return(-1);
  16. }
  17. else if(bytes_read==0)
  18. break;
  19. bytes_left-=bytes_read;
  20. ptr+=bytes_read;
  21. }
  22. return(length-bytes_left);
  23. }
复制代码

论坛徽章:
1
荣誉版主
日期:2011-11-23 16:44:17
5 [报告]
发表于 2003-04-17 15:15 |只看该作者

请教TCP SOCKET 的问题

你用的也可能是另外的读写函数,可以参考
1、recv和send
recv和send函数提供了和read和write差不多的功能.不过它们提供 了第四个参数来控制读写操作.

int recv(int sockfd,void *buf,int len,int flags)
int send(int sockfd,void *buf,int len,int flags)

前面的三个参数和read,write一样,第四个参数可以是0或者是以下的组合
_______________________________________________________________
| MSG_DONTROUTE | 不查找路由表 |
| MSG_OOB | 接受或者发送带外数据 |
| MSG_PEEK | 查看数据,并不从系统缓冲区移走数据 |
| MSG_WAITALL | 等待所有数据 |
|--------------------------------------------------------------|

MSG_DONTROUTE:是send函数使用的标志.这个标志告诉IP协议.目的主机在本地网络上面,没有必要查找路由表.这个标志一般用网络诊断和路由程序里面.
MSG_OOB:表示可以接收和发送带外的数据.关于带外数据我们以后会解释的.

MSG_PEEK:是recv函数的使用标志,表示只是从系统缓冲区中读取内容,而不清楚系统缓冲区的内容.这样下次读的时候,仍然是一样的内容.一般在有多个进程读写数据时可以使用这个标志.

MSG_WAITALL是recv函数的使用标志,表示等到所有的信息到达时才返回.使用这个标志的时候recv回一直阻塞,直到指定的条件满足,或者是发生了错误. 1)当读到了指定的字节时,函数正常返回.返回值等于len 2)当读到了文件的结尾时,函数正常返回.返回值小于len 3)当操作发生错误时,返回-1,且设置错误为相应的错误号(errno)

如果flags为0,则和read,write一样的操作.
2、recvfrom和sendto
这两个函数一般用在非套接字的网络程序当中(UDP)。
3、recvmsg和sendmsg
recvmsg和sendmsg可以实现前面所有的读写函数的功能.

int recvmsg(int sockfd,struct msghdr *msg,int flags)
int sendmsg(int sockfd,struct msghdr *msg,int flags)

struct msghdr
{
void *msg_name;
int msg_namelen;
struct iovec *msg_iov;
int msg_iovlen;
void *msg_control;
int msg_controllen;
int msg_flags;
}

struct iovec
{
void *iov_base; /* 缓冲区开始的地址 */
size_t iov_len; /* 缓冲区的长度 */
}

msg_name和 msg_namelen当套接字是非面向连接时(UDP),它们存储接收和发送方的地址信息.msg_name实际上是一个指向struct sockaddr的指针,msg_name是结构的长度.当套接字是面向连接时,这两个值应设为NULL. msg_iov和msg_iovlen指出接受和发送的缓冲区内容.msg_iov是一个结构指针,msg_iovlen指出这个结构数组的大小. msg_control和msg_controllen这两个变量是用来接收和发送控制数据时的 msg_flags指定接受和发送的操作选项.和recv,send的选项一样

论坛徽章:
0
6 [报告]
发表于 2003-04-17 16:10 |只看该作者

请教TCP SOCKET 的问题

谢谢大家.  我可能没有说清楚.   

我的程序是: 当有一个客户连接到来, 服务端就,建立一个客户连接
client_fd = accept (server_fd, .... )
客户连接一旦建立, 就一直连接,  以后客户端会时不时的写一些数据进来. 客户端写完一组数据也不会关断, 过一段时间会写下一组.  服务端不会往客户端写数据.

所以服务器程序这边也要一直开着等待新的数据.  只有当客户端关断了这个连接, 比如退出了,  服务端才 close(client_fd ). 我的问题是服务段如何知道客户端是否关断了这个连接呢?

论坛徽章:
0
7 [报告]
发表于 2003-04-17 16:23 |只看该作者

请教TCP SOCKET 的问题

你将FD_CLOSE事件置为有效,那么当客户端closesocket(sockID)通知服务端时,服务端就能检测到。

论坛徽章:
1
荣誉版主
日期:2011-11-23 16:44:17
8 [报告]
发表于 2003-04-17 16:31 |只看该作者

请教TCP SOCKET 的问题

楼上说的办法是可行的,另外如果,client主动close了,你的read或者recv会返回的。请仔细看看上面的贴子。你要的答案就在其中!

论坛徽章:
1
2015年辞旧岁徽章
日期:2015-03-03 16:54:15
9 [报告]
发表于 2003-04-17 16:38 |只看该作者

请教TCP SOCKET 的问题

用 select !
如果 select  探测到套节字可读,但是 read 到的数据长度却是 0,那么说明对方已经断开连接。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP