1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162
|
// TCP client that operates TCP connection in two threads: one thread that does blocking recv(),
// and another that does send()s
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <netdb.h>
#ifdef __EMSCRIPTEN__
#include <emscripten.h>
#include <emscripten/websocket.h>
#include <emscripten/threading.h>
EMSCRIPTEN_WEBSOCKET_T bridgeSocket = 0;
extern "C" {
EMSCRIPTEN_WEBSOCKET_T emscripten_init_websocket_to_posix_socket_bridge(const char *bridgeUrl);
}
#endif
int lookup_host(const char *host)
{
struct addrinfo hints, *res;
int errcode;
char addrstr[100];
void *ptr;
memset(&hints, 0, sizeof (hints));
hints.ai_family = PF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags |= AI_CANONNAME;
errcode = getaddrinfo(host, NULL, &hints, &res);
if (errcode != 0)
{
printf("getaddrinfo failed!\n");
return -1;
}
printf("Host: %s\n", host);
while (res)
{
inet_ntop(res->ai_family, res->ai_addr->sa_data, addrstr, 100);
switch (res->ai_family)
{
case AF_INET:
ptr = &((struct sockaddr_in *)res->ai_addr)->sin_addr;
break;
case AF_INET6:
ptr = &((struct sockaddr_in6 *)res->ai_addr)->sin6_addr;
break;
}
inet_ntop(res->ai_family, ptr, addrstr, 100);
printf("IPv%d address: %s (%s)\n", res->ai_family == PF_INET6 ? 6 : 4, addrstr, res->ai_canonname);
res = res->ai_next;
}
return 0;
}
_Atomic uint32_t pendingMessages = 0;
void *send_thread(void *arg)
{
int sock = (int)(intptr_t)arg;
for(int i = 0; i < 10; ++i)
{
char message[] = "hella";
message[4] += i;
while(pendingMessages != 0)
emscripten_thread_sleep(10);
printf("Send()ing\n");
if (send(sock, message, strlen(message), 0) < 0)
{
puts("Send failed");
pthread_exit((void*)1);
}
printf("Send() done\n");
pendingMessages++;
}
pthread_exit(0);
}
void *recv_thread(void *arg)
{
int sock = (int)(intptr_t)arg;
for(int i = 0; i < 10; ++i)
{
char server_reply[256] = {};
printf("Recv()ing\n");
if (recv(sock, server_reply, 256, 0) < 0)
{
puts("recv failed");
pthread_exit((void*)1);
}
printf("Recv() done\n");
puts("Server reply: ");
puts(server_reply);
pendingMessages--;
}
pthread_exit(0);
}
int main(int argc , char *argv[])
{
#ifdef __EMSCRIPTEN__
bridgeSocket = emscripten_init_websocket_to_posix_socket_bridge("ws://localhost:8080");
// Synchronously wait until connection has been established.
uint16_t readyState = 0;
do {
emscripten_websocket_get_ready_state(bridgeSocket, &readyState);
emscripten_thread_sleep(100);
} while(readyState == 0);
#endif
lookup_host("google.com");
// Create socket
int sock = socket(AF_INET, SOCK_STREAM, 0);
if (sock == -1)
{
printf("Could not create socket");
exit(1);
}
printf("Socket created: %d\n", sock);
struct sockaddr_in server;
server.sin_addr.s_addr = inet_addr("127.0.0.1");
server.sin_family = AF_INET;
server.sin_port = htons(8888);
if (connect(sock, (struct sockaddr *)&server, sizeof(server)) < 0)
{
perror("connect failed. Error");
return 1;
}
pthread_t sendThread;
pthread_t recvThread;
pthread_create(&recvThread, 0, &recv_thread, (void*)sock);
emscripten_thread_sleep(1000); // To get a better guarantee that the first recv() precedes the first send(), sleep for a moment between recv+send thread starts
pthread_create(&sendThread, 0, &send_thread, (void*)sock);
void *sendRet;
void *recvRet;
printf("Waiting for send thread to be finished\n");
pthread_join(sendThread, &sendRet);
printf("Send thread finished, waiting for recv thread to be finished\n");
pthread_join(recvThread, &recvRet);
printf("Send thread and recv thread finished\n");
close(sock);
if ((long)sendRet != 0) fprintf(stderr, "pthread send failed!\n");
if ((long)recvRet != 0) fprintf(stderr, "pthread recv failed!\n");
return 0;
}
|