我是 C 套接字编程的新手。我了解到,通过套接字发送数据后,应该关闭
或关闭
套接字描述符,这会触发将 EOF 发送到另一端。如果没有 EOF,read
/recv
会一直阻塞。
现在我想知道是否有可能保持套接字打开以进行进一步的数据传输。从我读到的内容来看,这似乎是人们在建立 keep-alive HTTP 连接时所做的事情。但我无法弄清楚这是如何实现的。
以下代码显示了在客户端写入
之后卡住的场景。
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#define thread_printf(...) printf("[PID %d] ", getpid()); printf(__VA_ARGS__);
int create_socket()
{
int socket_fd;
socket_fd = socket(AF_INET, SOCK_STREAM, 0);
if (socket_fd < 0)
perror("Error opening socket");
return socket_fd;
}
int listen_port(int portno)
{
int socket_fd;
struct sockaddr_in server_addr;
socket_fd = create_socket();
memset((void *) &server_addr, 0, sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(portno);
server_addr.sin_addr.s_addr = INADDR_ANY;
if (bind(socket_fd, (struct sockaddr *) &server_addr, sizeof(server_addr)) < 0)
perror("Error on binding");
listen(socket_fd, 5);
return socket_fd;
}
int connect_port(const char *host, int portno)
{
int socket_fd;
struct sockaddr_in proxy_addr;
struct hostent *proxy;
socket_fd = create_socket();
proxy = gethostbyname(host);
if (proxy == NULL)
perror("Error no such host");
proxy_addr.sin_family = AF_INET;
proxy_addr.sin_port = htons(portno);
memcpy((void *) &proxy_addr.sin_addr.s_addr, (void *) proxy->h_addr, proxy->h_length);
if (connect(socket_fd, (struct sockaddr *) &proxy_addr, sizeof(proxy_addr)) < 0)
perror("Error connecting");
return socket_fd;
}
int read_socket(int fd, char *buf, int bufsize)
{
thread_printf("read_socket\n");
int m = 0; /* total number of bytes received */
int n = 0; /* number of bytes received in a single read */
while (m < bufsize - 1)
{
n = read(fd, buf + m, bufsize - m - 1);
if (n == -1) /* socket read error */
{
perror("Error reading socket");
break;
}
if (n == 0) /* socket is closed */
break;
m += n;
}
if (m >= bufsize)
perror("Error buffer overflow");
buf[m] = '\0';
return m;
}
int write_socket(int fd, char *buf, int len)
{
thread_printf("write_socket\n");
int m = 0;
int n = 0;
while (m < len)
{
n = write(fd, buf + m, len - m);
if (n == -1) {
perror("Error socket send");
break;
}
if (n == 0) /* socket is closed */
break;
m += n;
}
thread_printf("m = %d, len = %d\n", m, len);
return m;
}
int main()
{
int socket_fd = listen_port(3129);
if (fork() == 0) /* client */
{
close(socket_fd);
int client_socket_fd = connect_port("127.0.0.1", 3129);
int n;
char *msg = "This is a client request\n";
char buf[1024];
memset((void *) buf, 0, 1024);
n = write_socket(client_socket_fd, msg, strlen(msg));
thread_printf("client sent: %s\n", msg);
n = read_socket(client_socket_fd, buf, 1024);
thread_printf("client received: %s\n", buf);
close(client_socket_fd);
}
else /* server */
{
struct sockaddr_in client_addr;
int client_len;
client_len = sizeof(client_addr);
int client_socket_fd = accept(socket_fd, (struct sockaddr *) &client_addr, &client_len);
int n;
char *msg = "This is a server response\n";
char buf[1024];
n = read_socket(client_socket_fd, buf, 1024);
thread_printf("server received: %s\n", buf);
n = write_socket(client_socket_fd, msg, strlen(msg));
thread_printf("server sent: %s\n", msg);
close(client_socket_fd);
}
return 0;
}
最佳答案
在服务器中,您的代码等待读取 1024 个字节,但在客户端中,您仅发送 26 个字节作为 strlen(msg)
,因此您的服务器永远不会从 read_socket
对于任何套接字客户端-服务器应用程序,您需要为客户端和服务器定义自己的协议(protocol),以决定何时确定已读取所有数据,或者通过确定固定长度的数据包,或者通过将数据长度作为数据本身的一部分
例如您可以决定您的数据将包括前 2 个字节作为数据长度,然后是实际数据
关于c - 在 C 中,如何在不关闭/关闭套接字的情况下写入数据后指示 EOF?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45747973/