在C中使用select()和write_fds时发送数据的正确方法

时间:2016-04-03 14:30:54

标签: c sockets select

所以我正在建立一个聊天服务器,现在我试图回应来自客户端的所有消息。目前,只要收到消息,我就会在readData()内将其发回。但是,只要我发送select(),就会write_fds通知sendData()并调用send(),即使我已拨打readData()

我发送数据的大多数调用都在select()内。

  • 这是使用write_fdsselect()吗?
  • 的正确方法
  • 如果没有两次拨打send(),我如何通知send()我想要发送数据?

我不得不处理对int readData(int j){ // get message from the client recv(j, client_buffer , 6000 , 0); // echo message to the client send(j, client_buffer, strlen(client_buffer)); } int sendData(int j){ send(j, buf, nbytes, 0); } for(;;){ read_fds = master; write_fds = master; if(select(fdmax+1, &read_fds, &write_fds, NULL, NULL) == -1){ exit(4); } for(i = 0; i <= fdmax; i++){ if(FD_ISSET(i, &read_fds)){ if(i == listener){ // handle new connections addrlen = sizeof remoteaddr; newfd = accept(listener, (struct sockaddr *)&addr, &addrlen); FD_SET(newfd, &master); if(newfd > fdmax) fdmax = newfd; }else{ // we got some data from a client readData(i); } } if(FD_ISSET(i, &write_fds)){ if(i != listener){ // send data when notified sendData(i); } } } } 的两次调用似乎多余。

{{1}}

1 个答案:

答案 0 :(得分:0)

我不建议直接在sendData()内调用readData()。它们应该分开。让readData()将接收到的数据返回给调用者,让调用者决定如何处理它。如果呼叫者想要发送数据,则可以根据需要调用sendData()

要解决select()问题,您需要为传出数据创建每个套接字缓冲区。并确保套接字以非阻塞模式运行。

  1. 如果缓冲区为空时调用sendData(),则send()尽可能多地调用调用者的数据。 send()将返回它实际接受的字节数。如果send()报告EWOULDBLOCKEAGAIN错误,请停止发送并将任何未发送的数据附加到缓冲区的末尾。

  2. 如果缓冲区不为空时调用sendData(),只需将新数据附加到缓冲区的末尾,然后退出而不调用send()

  3. 每当select()报告套接字是可写的,send()当前缓存在该套接字缓冲区中的任何内容(如果有的话)。对于每个成功的send(),从缓冲区前面删除报告的字节数。如果缓冲区耗尽或send()失败,则停止发送。