我正在使用Berkeley套接字(两者:Internet域和Unix域),我想知道服务器是否可以使用相同的套接字来读取请求并将响应写入客户端.或者客户端是否应该创建另一个套接字以等待重播,并且服务器在处理收到的消息后连接到它.
顺便说一句,我在谈论面向连接的套接字(流套接字,TCP,...).
这是简化的服务器代码(为了简单起见,我省略了对系统调用的错误检查):
int main() { int server_socket, connected_socket; struct sockaddr_in server_addr; char buf[1024]; char aux[256]; int bytes_read; server_socket = socket(AF_INET, SOCK_STREAM, 0); server_addr.sin_family = AF_INET; server_addr.sin_addr.s_addr = INADDR_ANY; server_addr.sin_port = htons(1234); bind(server_socket, &server_addr, sizeof(server_addr)) listen(server_socket, 5) connected_sodket = accept(server_socket, 0, 0); do { bzero(buf, sizeof(buf)); bytes_read = read(connected_socket, buf, sizeof(buf)); } while (bytes_read > 0); /* Here I want to use connected_socket to write the reply, can I? */ close(connected_socket); close(server_socket); return (EXIT_SUCCESS); }
这是简化的客户端代码(为了简单起见,我省略了对系统调用的错误检查):
int main() { int client_socket; struct sockaddr_in server_addr; client_socket = socket(AF_INET, SOCK_STREAM, 0); hp = gethostbyname("myhost"); server_addr.sin_family = AF_INET; memcpy(&server_addr.sin_addr, hp->h_addr_list[0], hp->h_length); server_addr.sin_port = htons(1234); connect(client_socket, &server_addr, sizeof(server_addr)); write(client_socket, MSG, sizeof(MSG)); /* Here I want to wait for a response from the server using client_socket, can I? */ close(client_socket); return (EXIT_SUCCESS); }
我可以connected_socket
在服务器和client_socket
客户端中使用来传回响应消息吗?或者我应该在"接受"连接到客户端的套接字时使用我在服务器中获得的客户端地址?
我已经尝试在显示注释的客户端/服务器中使用read/wrint,但这样两个程序都被阻塞,这似乎是一个死锁.
谢谢提前!问候.
你应该使用相同的插座!
您的应用程序协议明确定义了客户端和服务器何时应该等待数据或相互发送消息; 假设一个协议只有来自客户端的一个请求和一个来自服务器的响应,则应该包含以下内容:
客户端与服务器建立连接;
客户端发送请求(使用send());
客户端根据协议知道服务器将回复; 因此它等待同一个套接字上的数据(recv());
验证响应后,客户端可以关闭套接字.
服务器接受来自客户端的连接;
服务器知道第一步是由客户端决定,因此它等待数据(recv());
服务器验证请求;
服务器现在从协议中知道客户端正在等待数据; 因此它用send()发送响应;
服务器从协议中知道没有进一步的步骤; 因此它可以关闭套接字.
您可以使用相同的套接字但是您的程序设置为让服务器在尝试回复之前读取客户端发送的所有内容.因此,服务器中的循环将无法完成,直到客户端关闭其套接字的写入端,因此服务器获得EOF(读取0字节),因此服务器将永远不会发回其响应.
有几种方法可以解决这个问题.
您可以在看到整个请求后打破服务器中的循环,而不是直到EOF读取.这要求客户端发送的数据以某种方式自行分隔,因此服务器可以知道它何时读取它.
您可以使用第二个连接进行回复.可能不是最好的.
您可以使用套接字的非对称关闭.让客户端做shutdown(client_socket, SHUT_WR)
半关闭套接字.然后服务器将看到EOF(并且循环将完成),但是套接字上的另一个方向仍将打开以进行回复.