user-0 提问: Linux下socket编程问题

回复:
user: user-1
content: 不知道有多少前人掉在TCP Socket send(人多)send(病少)send(财富) recv(人多病)recv(少财富) 陷阱里面啊！ http://bbs.csdn.net/topics/380167545

user: user-0
content: 引用 9楼自信男孩 的回复:if((ret = read(sockfd, buffer, sizeof(buffer)-1) ) < 0) 问题主要出在这儿，仔细对比一下client程序里的这句。 写代码注意不要太随意哦，  以下是client的完整代码： #include <stdio.h> #include <unistd.h> #include <string.h> #include <sys/types.h> #include <netdb.h>  #define RET_ERR    -1 #define RET_OK    0 #define BUFFERSIZE    1024 #define ECHO_PORT    2029  int main(int argc, char *argv[]) {     int sockfd;     struct sockaddr_in servaddr;     struct hostent *server;     char buffer[BUFFERSIZE];     int ret;      if(argc < 2)     {         fprintf(stderr, "Usage:%s hostname\n", argv[0]);         return RET_ERR;     }      if((server=gethostbyname(argv[1])) == NULL)     {         hstrerror(h_errno);         return RET_ERR;     }      if((sockfd=socket(AF_INET, SOCK_STREAM, 0)) < 0)     {         perror("ERROR opening socket");         return RET_ERR;     }      memset(&servaddr, 0, sizeof(servaddr));     servaddr.sin_family = AF_INET;     servaddr.sin_addr.s_addr = *(uint32_t *)server->h_addr;     servaddr.sin_port = htons((uint16_t)ECHO_PORT);      if((ret=connect(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr))) < 0)     {         perror("ERROR connecting");         close(sockfd);         return RET_ERR;     }       while(1)     {         if(fgets(buffer, sizeof(buffer)-1, stdin) == NULL)         {             break;         }          if((ret=write(sockfd, buffer, strlen(buffer)) < 0))         {             perror("ERROR writing from socket");             break;         }         printf("send buffer = %s", buffer);          if((ret = read(sockfd, buffer, sizeof(buffer)-1) ) < 0)         {             perror("ERROR reading from socket");             break;         }         if(ret == 0)         {             printf("server disconnect\n");             break;         }          buffer[ret] = '\0';         printf("receive message:%s\n", buffer);      }      close(sockfd);      return RET_OK; }好low的错误，最近自己想重新回顾一下socket的代码，一开始碰到错误就懵了，感觉不会玩了，谢谢

user: user-2
content: if((ret = read(sockfd, buffer, sizeof(buffer)-1) ) < 0) 问题主要出在这儿，仔细对比一下client程序里的这句。 写代码注意不要太随意哦，  以下是client的完整代码： #include <stdio.h> #include <unistd.h> #include <string.h> #include <sys/types.h> #include <netdb.h>  #define RET_ERR    -1 #define RET_OK    0 #define BUFFERSIZE    1024 #define ECHO_PORT    2029  int main(int argc, char *argv[]) {     int sockfd;     struct sockaddr_in servaddr;     struct hostent *server;     char buffer[BUFFERSIZE];     int ret;      if(argc < 2)     {         fprintf(stderr, "Usage:%s hostname\n", argv[0]);         return RET_ERR;     }      if((server=gethostbyname(argv[1])) == NULL)     {         hstrerror(h_errno);         return RET_ERR;     }      if((sockfd=socket(AF_INET, SOCK_STREAM, 0)) < 0)     {         perror("ERROR opening socket");         return RET_ERR;     }      memset(&servaddr, 0, sizeof(servaddr));     servaddr.sin_family = AF_INET;     servaddr.sin_addr.s_addr = *(uint32_t *)server->h_addr;     servaddr.sin_port = htons((uint16_t)ECHO_PORT);      if((ret=connect(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr))) < 0)     {         perror("ERROR connecting");         close(sockfd);         return RET_ERR;     }       while(1)     {         if(fgets(buffer, sizeof(buffer)-1, stdin) == NULL)         {             break;         }          if((ret=write(sockfd, buffer, strlen(buffer)) < 0))         {             perror("ERROR writing from socket");             break;         }         printf("send buffer = %s", buffer);          if((ret = read(sockfd, buffer, sizeof(buffer)-1) ) < 0)         {             perror("ERROR reading from socket");             break;         }         if(ret == 0)         {             printf("server disconnect\n");             break;         }          buffer[ret] = '\0';         printf("receive message:%s\n", buffer);      }      close(sockfd);      return RET_OK; }

user: user-0
content: 引用 7楼自信男孩 的回复:[quote=引用 5 楼 mark_qzh 的回复:] [quote=引用 2楼JXES 的回复:] if (ret == 0)  {      close(nsock);     break; }server端收到消息就返回了，但是好像cliemt端没收到[/quote] 你的client发完就关闭socket了，服务器即使收到了你发的，但服务器还没发呢，你已经关了socket了，那客户端还怎么接收（client已经关了）[/quote]client不是阻塞的吗？他不是应该等待server端发送信息过来吗……难道read是非阻塞的吗

user: user-2
content: 引用 5 楼 mark_qzh 的回复:[quote=引用 2楼JXES 的回复:] if (ret == 0)  {      close(nsock);     break; }server端收到消息就返回了，但是好像cliemt端没收到[/quote] 你的client发完就关闭socket了，服务器即使收到了你发的，但服务器还没发呢，你已经关了socket了，那客户端还怎么接收（client已经关了）

user: user-0
content: 引用 1楼JXES 的回复:while(1)         {             if((ret = read(nsock, buffer, sizeof(buffer)-1)) < 0)             {                 perror("Error on read");                 close(nsock);                 close(sockfd);                 return RET_ERR;             } if (ret == 0) break; //不判定=0情况就死循环了             buffer[ret] = '\0';             printf("Server:receive message buffer = %s", buffer);             if((ret = write(nsock, buffer, strlen(buffer))) < 0)             {                 perror("Error on write");                 close(nsock);                 close(sockfd);                 return RET_ERR;             }             printf("Server:send message buffer = %s ret = %d\n", buffer, ret);         }   这里面有问题，循环退不出了，当client没有发时，这里ret = 0,所以在里面要加一句如上。read函数不是阻塞的吗？没有数据它应该阻塞吧

user: user-0
content: 引用 2楼JXES 的回复:if (ret == 0)  {      close(nsock);     break; }server端收到消息就返回了，但是好像cliemt端没收到

user: user-0
content: 引用 2楼JXES 的回复:if (ret == 0)  {      close(nsock);     break; }我现在的问题是我client发了一个字符串过去，client断开连接，server端就进入死循环了

user: user-2
content: 注意，你的判定只是限于发送和接收出错时，若client正常关闭，你没有处理。加上read返回0时，直接close(nsock);

user: user-3
content: if (ret == 0)  {      close(nsock);     break; }

user: user-3
content: while(1)         {             if((ret = read(nsock, buffer, sizeof(buffer)-1)) < 0)             {                 perror("Error on read");                 close(nsock);                 close(sockfd);                 return RET_ERR;             } if (ret == 0) break; //不判定=0情况就死循环了             buffer[ret] = '\0';             printf("Server:receive message buffer = %s", buffer);             if((ret = write(nsock, buffer, strlen(buffer))) < 0)             {                 perror("Error on write");                 close(nsock);                 close(sockfd);                 return RET_ERR;             }             printf("Server:send message buffer = %s ret = %d\n", buffer, ret);         }   这里面有问题，循环退不出了，当client没有发时，这里ret = 0,所以在里面要加一句如上。