Cpp socket client server

Saved searches

Use saved searches to filter your results more quickly

You signed in with another tab or window. Reload to refresh your session. You signed out in another tab or window. Reload to refresh your session. You switched accounts on another tab or window. Reload to refresh your session.

kusdavletov/socket-programming-simple-server-and-client

This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Name already in use

A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?

Sign In Required

Please sign in to use Codespaces.

Launching GitHub Desktop

If nothing happens, download GitHub Desktop and try again.

Launching GitHub Desktop

If nothing happens, download GitHub Desktop and try again.

Launching Xcode

If nothing happens, download Xcode and try again.

Launching Visual Studio Code

Your codespace will open once ready.

There was a problem preparing your codespace, please try again.

Latest commit

Git stats

Files

Failed to load latest commit information.

README.md

C Socket Programming: Simple Server and Client

server.c — multithreaded server

server_single.c — singlethreaded server

This is pre-project tutorial for socket programming

If you are familiar to socket programming, then jump to Let’s Practice Part

  • With socket, two different processes can communicate each other
  • Socket is nothing but a file
  • You can just imagine that two different processes have files (socket) and the they read received data from socket and write to socket for sending data to network
  • So, socket has file descriptor, which is just an integer to identify opened file

There are two commonly used socket types Stream Sockets and Datagram Sockets . Stream sockets uses TCP for data transmission, and Datagram sockets uses UDP.

3. Client Process & Server Process

Client : Typically request to server for information.

  • Create a socket with the socket() system call
  • Connect socket to the address of the server using the connect() system call
  • Send and receive data. There are a number of ways to do this, but the simplest way is to use the read() and write() system calls

Server : Takes request from the clients, perform required processing, and send it to the client

  • Create a socket with the socket() system call
  • Bind the socket to an address (IP + port) using the bind() system call.
  • Listen for connections with the listen() system call
  • Accept a connection with the accept() system call. This call typically blocks the connection until a client connects with the server
  • Send and receive data using the read() and write() system calls

Interaction between server and client

Preliminary knowledge before programming

You will use socket functions, and most of the socket functions use socket address structures.

struct sockaddr < // represents an address family, most of cases AF_INET) unsigned short sa_family; // 14 bytes of protocol specific address, for the internet // family, port number IP address (sockaddr_in) is used char sa_data[14]; >
struct sockaddr_in < short int sin_family; // AF_INET unsigned short int sin_port; // 16-bit port number struct in_addr sin_addr; // 32-bit IP address unsigned char sin_zero[8]; >
struct in_addr < unsigned long s_addr; >
struct hostent < char *h_name; // e.g. unist.ac.kr char **h_aliases; // list of host name alias int h_addrtype; // AF_INET int h_length; // length of ip address char **h_addr_list; // points to structure in_addr #define h_addr h_addr_list[0] >;

All computers doesn’t store bytes in same order. → Two different ways

  • Little Endian : low-order byte is stored on the starting addresses
  • Bit Endian : high-order byte is stored on the starting address

→ To make machines with different byte order communicate each other, Internet protocol specify a canonical byte order convention for data transmitted over the network. This is called Network Byte Order.

sin_port sin_addr of sockaddr_in should be set with this Network Byte Order.

htons() : Host to Network Short htonl() : Host to Network Long ntohl() : Network to Host Long ntohs() : Network to Host Short

These functions manipulate IP addresses between ASCII strings and network byte ordered binary values.

#include arpa/inet.h> int retval; struct in_addr addrptr memset(&addrptr, '\0', sizeof(addrptr)); retval = inet_aton("68.178.157.132", &addrptr);
#include arpa/inet.h> struct sockaddr_in dest; memset(&dest, '\0', sizeof(dest)); dest.sin_addr.s_addr = inet_addr("68.178.157.132");

char *inet_ntoa(struct in_addr inaddr)

#include arpa/inet.h> char *ip; ip = inet_ntoa(dest.sin_addr); printf("IP Address is : %s\n", ip);

(you can use bold scripted parameter for the first use)

#include sys/types.h> #include sys/socket.h> int socket (int family, int type, int protocol);
  • family : AF_INET, AF_INET6, AF_LOCAL, AF_ROUTE, AF_KEY
  • type : SOCK_STREAM (TCP), SOCK_DGRAM (UDP), SOCK_SEQPACKET, SOCK_RAW
  • protocol : IPPROTO_TCP, IPPROTO_UDP, IPPROTO_SCTP, (0 : system default)

→ This function returns socket descriptor, so you can use it for another functions

#include sys/types.h> #include sys/socket.h> int connect(int sockfd, struct sockaddr *serv_addr, int addrlen);
  • sockfd : socket descriptor returned by the socket function
  • serv_addr : sockaddr that contains destination IP address and port
  • addrlen : set it to sizeof(struct sockaddr)
  1. bind
#include sys/types.h> #include sys/socket.h> int bind(int sockfd, struct sockaddr *my_addr,int addrlen);
#include sys/types.h> #include sys/socket.h> int listen(int sockfd,int backlog);
  • converts unconnected socket to passive socket (kernel should accept incoming connection request directed to this socket)
  • backlog : maximum number of connections the kernel should queue for this socket
  1. accept
#include sys/types.h> #include sys/socket.h> int accept (int sockfd, struct sockaddr *cliaddr, socklen_t *addrlen)
  • returns the next completed connection from the front of the completed connection queue
  • cliaddr : sockaddr struct that contains client IP address and port
  • addrlen : set it to sizeof (struct sockaddr)
  1. send
int send(int sockfd, const void *msg, int len, int flags);
int recv(int sockfd, void *buf, int len, unsigned int flags);
  • buf : buffer to read the information into
  • len : It is the maximum length of the buffer
  • flags : set it to 0
  1. for UDP connection
int sendto(int sockfd, const void *msg, int len, unsigned int flags, const struct sockaddr *to, int tolen); int recvfrom(int sockfd, void *buf, int len, unsigned int flags struct sockaddr *from, int *fromlen);
  1. fork
  • creates new process which is exact copy of current process
  • current process is parent, and copied process is child
#include sys/types.h> #include unistd.h> int fork(void);
  • fork returns 0 when it is child process, and returns child process id when it is parent process. If it is failed, returns -1
  1. bzero
  • place nbytes of null byte to string s
void bzero(void *s, int nbyte);
int bcmp(const void *s1, const void *s2, int nbyte);

returns 0 if identical, 1 otherwise.

void bcopy(const void *s1, void *s2, int nbyte);
void *memset(void *s, int c, int nbyte);
  • s : source to be set
  • c : character to set on nbyte places
  • nbyte : number of bytes

6. Let’s Practice : echo server and client

  • You have to implement connecting server and client, and your server and client should quit when the client sends “quit” you can compile code with command line in the directory of project :

7. Practice more! : multi user server

  • There can be multiple clients which tries to connect to server simultaneously
  • Current echo server doesn’t accept new connection if it is already accepted
  • You have to change echo server. Using fork() function, each connection should be run concurrently.
  • Hint (pseudo code of multi user server) :
  • Test : you can just open three terminal windows, run one server and two clients
  • test order :
> run one server and two clients > client1 sends “hello1” > client2 sends “hello2” > client2 sends “world2” > client1 sends “world1” > client1 sends “quit” and client2 sends “quit” 

Источник

Cpp socket client server

БлогNot. Пишем консольный сервер и клиент на C++ в Windows 32/64

Пишем консольный сервер и клиент на C++ в Windows 32/64

Как обычно, создаём новый пустой проект C++, но для решения указываем имя, например, ClientServer , а для проекта — другое имя, пусть будет Server .

Потом ещё раз создаём пустой проект с именем Client , но добавляем его в то то же самое решение.

Жмём правую кнопку мыши на «исходных файлах» приложения-сервера, выбираем команды Добавить, Создать элемент, Visual C++, файл C++, имя файла с исходным текстом можно оставить Source.cpp (по умолчанию).

Вот полный исходник этого файла, откомпилированный в Visual Studio 2019 под актуальной сборкой Windows 10.

#define _WINSOCK_DEPRECATED_NO_WARNINGS #include #include #include #include #pragma comment(lib, "WS2_32.lib") using namespace std; DWORD WINAPI serverReceive(LPVOID lpParam) < //Получение данных от клиента char buffer[1024] = < 0 >; //Буфер для данных SOCKET client = *(SOCKET*)lpParam; //Сокет для клиента while (true) < //Цикл работы сервера if (recv(client, buffer, sizeof(buffer), 0) == SOCKET_ERROR) < //Если не удалось получить данные буфера, сообщить об ошибке и выйти cout if (strcmp(buffer, "exit\n") == 0) < //Если клиент отсоединился cout cout return 1; > DWORD WINAPI serverSend(LPVOID lpParam) < //Отправка данных клиенту char buffer[1024] = < 0 >; SOCKET client = *(SOCKET*)lpParam; while (true) < fgets(buffer, 1024, stdin); if (send(client, buffer, sizeof(buffer), 0) == SOCKET_ERROR) < cout if (strcmp(buffer, "exit\n") == 0) < cout > return 1; > int main() < WSADATA WSAData; //Данные SOCKET server, client; //Сокеты сервера и клиента SOCKADDR_IN serverAddr, clientAddr; //Адреса сокетов WSAStartup(MAKEWORD(2, 0), &WSAData); server = socket(AF_INET, SOCK_STREAM, 0); //Создали сервер if (server == INVALID_SOCKET) < cout serverAddr.sin_addr.s_addr = INADDR_ANY; serverAddr.sin_family = AF_INET; serverAddr.sin_port = htons(5555); if (bind(server, (SOCKADDR*)&serverAddr, sizeof(serverAddr)) == SOCKET_ERROR) < cout if (listen(server, 0) == SOCKET_ERROR) < //Если не удалось получить запрос cout cout HANDLE t2 = CreateThread(NULL, 0, serverSend, &client, 0, &tid); //Создание потока для отправки данных if (t2 == NULL) < cout WaitForSingleObject(t1, INFINITE); WaitForSingleObject(t2, INFINITE); closesocket(client); //Закрыть сокет if (closesocket(server) == SOCKET_ERROR) < //Ошибка закрытия сокета cout WSACleanup(); > >

Я выбрал в стандартной панели инструментов конфигурацию Debug — X64. Если нужно, разрешить приложению работать с сетью, подтверждаем это.

Разрешить консольному приложению сервера доступ к сети

Разрешить консольному приложению сервера доступ к сети

Аналогично добавляем файл Source.cpp в приложение Client , вот его полный исходный код, так как он, в сущности, очень похож, можно без столь подробных комментариев:

#define _WINSOCK_DEPRECATED_NO_WARNINGS #include #include #include #include #pragma comment(lib, «WS2_32.lib») using namespace std; DWORD WINAPI clientReceive(LPVOID lpParam) < //Получение данных от сервера char buffer[1024] = < 0 >; SOCKET server = *(SOCKET*)lpParam; while (true) < if (recv(server, buffer, sizeof(buffer), 0) == SOCKET_ERROR) < cout if (strcmp(buffer, "exit\n") == 0) < cout cout return 1; > DWORD WINAPI clientSend(LPVOID lpParam) < //Отправка данных на сервер char buffer[1024] = < 0 >; SOCKET server = *(SOCKET*)lpParam; while (true) < fgets(buffer, 1024, stdin); if (send(server, buffer, sizeof(buffer), 0) == SOCKET_ERROR) < cout if (strcmp(buffer, "exit") == 0) < cout > return 1; > int main() < WSADATA WSAData; SOCKET server; SOCKADDR_IN addr; WSAStartup(MAKEWORD(2, 0), &WSAData); if ((server = socket(AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET) < cout addr.sin_addr.s_addr = inet_addr("127.0.0.1"); //коннект к серверу addr.sin_family = AF_INET; addr.sin_port = htons(5555); //порт if (connect(server, (SOCKADDR*)&addr, sizeof(addr)) == SOCKET_ERROR) < cout cout

Обратите внимание на директивы покдлючения библиотек в начале обоих листингов.

В Обозревателе Решений жмём правую кнопку на заголовке решения (самого верхнего уровня), выбираем «Назначить запускаемые проекты», подтверждаем запуск нескольких проектов.

Запуск нескольких проектов из решения

Запуск нескольких проектов из решения

Наши клиент и сервер могут обмениваться сообщениями в режиме чата, конечно, функционал нетрудно расширить. Работа приложения предполагает, что у вас есть нужные компоненты в системе и настройки стандартны, в частности, доступен стандартный «локалхост» с IP-адресом 127.0.0.1

Проект в работе

Проект в работе

Так как опции решения хранятся в файле .suo вместе с асболютными путями к файлам проекта (а у вас эти пути точно не совпадут с моими), то действие со второго рисунка («Запуск нескольких проектов из решения») в скачанном проекте будет не настроено.

28.07.2020, 01:02 [18979 просмотров]

Источник

Читайте также:  Empty space with css
Оцените статью