-
-
Save jirihnidek/388271b57003c043d322 to your computer and use it in GitHub Desktop.
#include <arpa/inet.h> | |
#include <netinet/in.h> | |
#include <stdio.h> | |
#include <stdlib.h> | |
#include <sys/socket.h> | |
#include <unistd.h> | |
#define SERVER_PORT 7002 | |
int main(int argc, char *argv[]) | |
{ | |
int sock_fd = -1; | |
struct sockaddr_in6 server_addr; | |
int ret; | |
char ch = 'a'; | |
/* Arguments could be used in getaddrinfo() to get e.g. IP of server */ | |
(void)argc; | |
(void)argv; | |
/* Create socket for communication with server */ | |
sock_fd = socket(AF_INET6, SOCK_STREAM, IPPROTO_TCP); | |
if (sock_fd == -1) { | |
perror("socket()"); | |
return EXIT_FAILURE; | |
} | |
/* Connect to server running on localhost */ | |
server_addr.sin6_family = AF_INET6; | |
inet_pton(AF_INET6, "::1", &server_addr.sin6_addr); | |
server_addr.sin6_port = htons(SERVER_PORT); | |
/* Try to do TCP handshake with server */ | |
ret = connect(sock_fd, (struct sockaddr*)&server_addr, sizeof(server_addr)); | |
if (ret == -1) { | |
perror("connect()"); | |
close(sock_fd); | |
return EXIT_FAILURE; | |
} | |
/* Send data to server */ | |
ret = write(sock_fd, &ch, 1); | |
if (ret == -1) { | |
perror("write"); | |
close(sock_fd); | |
return EXIT_FAILURE; | |
} | |
/* Wait for data from server */ | |
ret = read(sock_fd, &ch, 1); | |
if (ret == -1) { | |
perror("read()"); | |
close(sock_fd); | |
return EXIT_FAILURE; | |
} | |
printf("Received %c from server\n", ch); | |
/* DO TCP teardown */ | |
ret = close(sock_fd); | |
if (ret == -1) { | |
perror("close()"); | |
return EXIT_FAILURE; | |
} | |
return EXIT_SUCCESS; | |
} |
# Main CMakeFile.txt | |
# Minimal version of CMake | |
cmake_minimum_required (VERSION 2.6) | |
# Build type | |
if (NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES) | |
message(STATUS "Setting build type to 'Debug' as none was specified.") | |
set(CMAKE_BUILD_TYPE Debug CACHE STRING "Choose the type of build." FORCE) | |
# Set the possible values of build type for cmake-gui | |
set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "Debug" "Release") | |
endif () | |
# Define project name | |
project (Client-Server) | |
# Source code for server | |
set (server_src server.c) | |
# Source code for client | |
set (client_src client.c) | |
# Compiler flags | |
if (CMAKE_COMPILER_IS_GNUCC) | |
set (CMAKE_C_FLAGS "-D_REETRANT -Wall -Wextra -pedantic -Wno-long-long") | |
if (CMAKE_BUILD_TYPE STREQUAL "Debug") | |
set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -ggdb -O0") | |
elseif( CMAKE_BUILD_TYPE STREQUAL "Release" ) | |
set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DNDEBUG -O3 -fno-strict-aliasing") | |
endif () | |
endif (CMAKE_COMPILER_IS_GNUCC) | |
# Set up verse server executable | |
add_executable (server ${server_src}) | |
# Set up verse server executable | |
add_executable (client ${client_src}) |
#include <arpa/inet.h> | |
#include <stdio.h> | |
#include <stdlib.h> | |
#include <sys/socket.h> | |
#include <sys/types.h> | |
#include <unistd.h> | |
#include <netinet/in.h> | |
#define CLIENT_QUEUE_LEN 10 | |
#define SERVER_PORT 7002 | |
int main(void) | |
{ | |
int listen_sock_fd = -1, client_sock_fd = -1; | |
struct sockaddr_in6 server_addr, client_addr; | |
socklen_t client_addr_len; | |
char str_addr[INET6_ADDRSTRLEN]; | |
int ret, flag; | |
char ch; | |
/* Create socket for listening (client requests) */ | |
listen_sock_fd = socket(AF_INET6, SOCK_STREAM, IPPROTO_TCP); | |
if(listen_sock_fd == -1) { | |
perror("socket()"); | |
return EXIT_FAILURE; | |
} | |
/* Set socket to reuse address */ | |
flag = 1; | |
ret = setsockopt(listen_sock_fd, SOL_SOCKET, SO_REUSEADDR, &flag, sizeof(flag)); | |
if(ret == -1) { | |
perror("setsockopt()"); | |
return EXIT_FAILURE; | |
} | |
server_addr.sin6_family = AF_INET6; | |
server_addr.sin6_addr = in6addr_any; | |
server_addr.sin6_port = htons(SERVER_PORT); | |
/* Bind address and socket together */ | |
ret = bind(listen_sock_fd, (struct sockaddr*)&server_addr, sizeof(server_addr)); | |
if(ret == -1) { | |
perror("bind()"); | |
close(listen_sock_fd); | |
return EXIT_FAILURE; | |
} | |
/* Create listening queue (client requests) */ | |
ret = listen(listen_sock_fd, CLIENT_QUEUE_LEN); | |
if (ret == -1) { | |
perror("listen()"); | |
close(listen_sock_fd); | |
return EXIT_FAILURE; | |
} | |
client_addr_len = sizeof(client_addr); | |
while(1) { | |
/* Do TCP handshake with client */ | |
client_sock_fd = accept(listen_sock_fd, | |
(struct sockaddr*)&client_addr, | |
&client_addr_len); | |
if (client_sock_fd == -1) { | |
perror("accept()"); | |
close(listen_sock_fd); | |
return EXIT_FAILURE; | |
} | |
inet_ntop(AF_INET6, &(client_addr.sin6_addr), | |
str_addr, sizeof(str_addr)); | |
printf("New connection from: %s:%d ...\n", | |
str_addr, | |
ntohs(client_addr.sin6_port)); | |
/* Wait for data from client */ | |
ret = read(client_sock_fd, &ch, 1); | |
if (ret == -1) { | |
perror("read()"); | |
close(client_sock_fd); | |
continue; | |
} | |
/* Do very useful thing with received data :-) */ | |
ch++; | |
/* Send response to client */ | |
ret = write(client_sock_fd, &ch, 1); | |
if (ret == -1) { | |
perror("write()"); | |
close(client_sock_fd); | |
continue; | |
} | |
/* Do TCP teardown */ | |
ret = close(client_sock_fd); | |
if (ret == -1) { | |
perror("close()"); | |
client_sock_fd = -1; | |
} | |
printf("Connection closed\n"); | |
} | |
return EXIT_SUCCESS; | |
} |
Hey can you tell me how to use send()
with this. BTW Thanks its awesome
Hi @AniketMohan,
I have another gists. The send()
is used e.g. in this: https://gist.github.com/jirihnidek/9235597. It is maybe more complicated than necessary (it explains punch holing into firewall), but basic trick is that you probably have to use UDP and you have to call connect()
before using send()
. Without connect()
you have to use sendto()
.
Hey, thanks for the example! Special thanks for using a good coding style :)
Hey there, whenever I try run the server code, Im gettng this error: (bind(): Cannot assign requested address) could you help me?
Hi @TaikoG,
The example uses IPv6. Do you have IPv6 enabled on your system?
@jirihnidek Yes, I do currently running on windows 11.
You can enable IPv6 on Windows 11.
@nageshshamnur Finally, I changed this by using global address(as I did with link-local address previously), and it works now. I am confused with the link connect, not sure how to tell whether they are local-linked between two computers, actually I am using gateway.