In C, how to indicate EOF after writing data without close/shutdown a socket? -
i new c socket programming. learned after sending data through socket, 1 should either close
or shutdown
socket descriptor, triggers eof sent other end. without eof, read
/recv
keeps blocking.
now wondering if possible @ keep socket open further data transfer. read, seems people when establish keep-alive http connection. not figure out how achieved.
the following code shows scenario, stuck after client's write
.
#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 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 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 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 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 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; }
in server code waits read 1024 bytes in client sending 26 bytes strlen(msg)
, server never return read_socket
as socket client-server application, need define own protocol client , server when conclude data has been read, either deciding fixed length packets or including length of data part of data itself
e.g. can decide data include, first 2 bytes length of data followed actual data
Comments
Post a Comment