/* * Author, Copyright: Oleg Borodin <onborodin@gmail.com> */ #ifndef MSG_H_IUYTR #define MSG_H_IUYTR #include <stdio.h> #include <sys/endian.h> #include <string.h> typedef struct msg_hdr { uint16_t version; uint32_t id; uint16_t type; uint64_t csize; uint16_t pnumber; uint16_t pcount; uint64_t psize; uint64_t poffset; } msg_hdr_t; typedef struct msg { msg_hdr_t header; void* content; } msg_t; void msg_hdr_encode (msg_hdr_t* net, msg_hdr_t* host) { net->id = htobe32(host->id); net->version = htobe16(host->version); net->type = htobe16(host->type); net->csize = htobe64(host->csize); net->pnumber = htobe16(host->pnumber); net->pcount = htobe16(host->pcount); net->psize = htobe16(host->psize); net->poffset = htobe16(host->poffset); } void msg_hdr_decode (msg_hdr_t* host, msg_hdr_t* net) { host->id = be32toh(net->id); host->version = be16toh(net->version); host->type = be16toh(net->type); host->csize = be64toh(net->csize); host->pnumber = be16toh(net->pnumber); host->pcount = be16toh(net->pcount); host->psize = be16toh(net->psize); host->poffset = be16toh(net->poffset); } #define MSG_VER1 1 void msg_init(msg_t* m) { memset(m, 0, sizeof(msg_t)); m->header.version = (MSG_VER1 | 0xFE00); } void msg_set_size(msg_t* m, uint64_t size) { m->header.csize = size; } uint64_t msg_get_size(msg_t* m) { return m->header.csize; } #endif
/* * Author, Copyright: Oleg Borodin <onborodin@gmail.com> */ #include <stdlib.h> #include <stdio.h> #include <stdbool.h> #include <unistd.h> #include <string.h> #include <fcntl.h> #include <pthread.h> #include <sys/event.h> #include <sys/types.h> #include <sys/socket.h> #include <arpa/inet.h> #include <netinet/in.h> #include <sys/time.h> #include <err.h> #include <sys/endian.h> #include "msg.h" int socket_create(int port, int backlog) { int sock; if((sock = socket(PF_INET, SOCK_STREAM, 0)) < 0) { fprintf(stderr, "cannot create socket, exit\n"); exit(1); } int optval; optval = 1; if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval)) < 0) { fprintf(stderr, "cannot set socket option, exit\n"); exit(1); } struct sockaddr addr; struct sockaddr_in* paddr = (struct sockaddr_in*)&addr; paddr->sin_family = AF_INET; paddr->sin_addr.s_addr = INADDR_ANY; paddr->sin_port = htons(port); paddr->sin_len = sizeof(struct sockaddr_in); if (bind(sock, (struct sockaddr*)paddr, paddr->sin_len) < 0) { fprintf(stderr, "cannot bind socket, exit\n"); exit(1); } if (listen(sock, backlog) < 0) { fprintf(stderr, "cannot listen socket, exit\n"); exit(1); } return sock; } int main(int argc, char **argv) { int sock = socket_create(1024, 4096); while (1) { int newsock = 0; if ((newsock = accept(sock, NULL, 0)) > 3) { struct timeval tv; tv.tv_sec = 3; tv.tv_usec = 0; if (setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(struct timeval)) < 0) { fprintf(stderr, "cannot set socket option, exit\n"); exit(1); } const int bsize = 1024; char buffer[bsize]; int rv = read(newsock, buffer, sizeof(msg_hdr_t)); if (rv == sizeof(msg_hdr_t)) { fprintf(stderr, "receive header:\n"); msg_hdr_t msgh; memcpy(&msgh, buffer, sizeof(msg_hdr_t)); msg_hdr_t h; msg_hdr_decode(&h, &msgh); fprintf(stderr, "size: %ld\n", h.csize); if ((rv = read(newsock, buffer, h.csize)) == h.csize) { buffer[h.csize + 1] = 0; fprintf(stderr, "content: %s\n", buffer); } } close(newsock); } } close(sock); return 0; }
/* * Author, Copyright: Oleg Borodin <onborodin@gmail.com> */ #include <stdlib.h> #include <stdio.h> #include <stdbool.h> #include <unistd.h> #include <string.h> #include <fcntl.h> #include <pthread.h> #include <sys/event.h> #include <sys/types.h> #include <sys/socket.h> #include <arpa/inet.h> #include <netinet/in.h> #include <sys/time.h> #include <err.h> #include <netinet/ip.h> #include <netdb.h> #include <sys/endian.h> #include "msg.h" int sock_connect(char* hostname, const int port) { int sock; if ((sock = socket(PF_INET, SOCK_STREAM, 0)) < 0) { return -1; } struct addrinfo hints; memset(&hints, 0, sizeof(hints)); hints.ai_family = AF_INET; hints.ai_socktype = SOCK_STREAM; hints.ai_protocol = IPPROTO_TCP; struct addrinfo* result = NULL; int retval; if ((retval = getaddrinfo(hostname, NULL, &hints, &result)) != 0) { return -1; } struct sockaddr_in* sockaddr = NULL; for (struct addrinfo* ptr = result; ptr != NULL; ptr = ptr->ai_next) { switch (ptr->ai_family) { case AF_INET: sockaddr = (struct sockaddr_in*)ptr->ai_addr; break; default: break; } if (sockaddr != NULL) { break; } } struct sockaddr addr; memset(&addr, 0, sizeof(struct sockaddr)); memcpy(&addr, sockaddr, sizeof(struct sockaddr_in)); freeaddrinfo(result); struct sockaddr_in* paddr = (struct sockaddr_in*)&addr; paddr->sin_family = AF_INET; paddr->sin_port = htons(port); paddr->sin_len = sizeof(struct sockaddr_in); if (connect(sock, (struct sockaddr*)paddr, paddr->sin_len) < 0) { return -1; } return sock; } int main(int argc, char **argv) { int sock = sock_connect("localhost", 1024); char buffer[1024]; memset(buffer, 'z', 1024); //char data[] = "hello, world!"; msg_t m; msg_init(&m); if (argc > 1) { m.content = argv[1]; m.header.csize = strlen(argv[1]); } msg_hdr_t n; msg_hdr_encode(&n, &(m.header)); write(sock, &n, sizeof(msg_hdr_t)); write(sock, m.content, m.header.csize); //sleep(1); close(sock); return 0; }
$ ./msg-client hello,world