- Programming UDP sockets in C on Linux – Client and Server example
- UDP sockets
- Simple UDP Server
- UDP Client
- Conclusion
- 16 thoughts on “ Programming UDP sockets in C on Linux – Client and Server example ”
- Клиент-Сервер Socket linux (Система обмена сообщениями)
- Деревянные треды лора: помогите решить ДЗ
- Еще вопросик:
- Re: Еще вопросик:
Programming UDP sockets in C on Linux – Client and Server example
UDP sockets
This article describes how to write a simple echo server and client using udp sockets in C on Linux/Unix platform.
UDP sockets or Datagram sockets are different from the TCP sockets in a number of ways.
The most important difference is that UDP sockets are not connection oriented. More technically speaking, a UDP server does not accept connections and a udp client does not connect to server.
The server will bind and then directly receive data and the client shall directly send the data.
Simple UDP Server
So lets first make a very simple ECHO server with UDP socket. The flow of the code would be
socket() -> bind() -> recvfrom() -> sendto()
Run the above code by doing a gcc server.c && ./a.out at the terminal. Then it will show waiting for data like this
Next step would be to connect to this server using a client. We shall be making a client program a little later but first for testing this code we can use netcat.
Test the server with netcat
Open another terminal and connect to this udp server using netcat and then send some data. The same data will be send back by the server. Over here we are using the ncat command from the nmap package.
Note : We had to use netcat because the ordinary telnet command does not support udp protocol. The -u option of netcat specifies udp protocol.
Check open port with netstat
The netstat command can be used to check if the udp port is open or not.
Note the *:8888 entry of output. Thats our server program.
The entry that has localhost:8888 in «Foreign Address» column, indicates some client connected to it, which is netcat over here.
UDP Client
Now that we have tested our server with netcat, its time to make a client and use it instead of netcat.
The program flow is like
Here is a quick example
‘, BUFLEN); //try to receive some data, this is a blocking call if (recvfrom(s, buf, BUFLEN, 0, (struct sockaddr *) &si_other, &slen) == -1) < die("recvfrom()"); >puts(buf); > close(s); return 0; >
Run the above program and it will ask for some message
Whatever message the client sends to server, the same comes back as it is and is echoed.
Conclusion
UDP sockets are used by protocols like DNS etc. The main idea behind using UDP is to transfer small amounts of data and where reliability is not a very important issue. UDP is also used in broadcasting/multicasting.
When a file transfer is being done or large amount of data is being transferred in parts the transfer has to be much more reliable for the task to complete. Then the TCP sockets are used.
A Tech Enthusiast, Blogger, Linux Fan and a Software Developer. Writes about Computer hardware, Linux and Open Source software and coding in Python, Php and Javascript. He can be reached at [email protected] .
16 thoughts on “ Programming UDP sockets in C on Linux – Client and Server example ”
Hello. You seem to have double pasted the second code sample inside itself. THanks for the tutorial
Hey Silver Moon,
I’m a not a programmer but are very interested in electronics and making things automated. This was very helpful example of udp socket communications. What I did find though was the program doesn’t do anything else whilst it waits for data. How would you suggest to say send this server “Blink Led 1” and continue to listen for commands to turn on, blink or turn off leds.
I can for example blink the led no problem in one project, I can get you code also running on a pi and responding to commands I send it now but I would like to be able to continue doing things in the background.
Thanks for you time.
i haven’t done sockets for a long time. right now i can think of using multiple threads do things in parallel.
so the main thread could do its background work, and an extra thread could listen to the udp port for incoming messages.
or the other way round.
but i am not sure if that is the best approach. there might be better alternatives.
Silver Moon’s approach will work but the best way would be to listen for socket connections asynchronously using epoll() and using TCP not UDP, UDP is unreliable so some of your commands might not make it to the server as intended. That’s what is done in most modern socket servers. Try googling how to use epoll() (Linux system call so should work on Raspberry Pi). It will allow you to have an efficient and scalable socket server. (I am actually almost done developing an IoT socket communication system myself using raspberry pi as main server and epoll() with TCP is the best approach for this kind of stuff as far as I know.
Thx! This article was really helpful for understanding some basic things about socket programming.
Thank you so much for this, it was really helpful!
update note: Ubuntu 16.04.3. gcc 5.4.0 complained until slen was declared unsigned int.
And ncat used option -vv which on my Ubuntu system means verbose. The captured text does not have the verbose output. My system had five lines of information for each line of typed in data.
Still, I am new to Linux and Ubuntu and this is an unexpected cool way to test the server app.
Thank you.
Very helpful. Thanks!
Hi, I am new to socket programminga and linux , can you tell me … can we turn a system into a server ? and do communication using above programming? can we establish communication on the microcontroller using above programs?
Excelent example, thanks very much!
I’ve found that it needs only a tiny addition.
To clean the buffer on the server also. So just adding on Server:
//keep listening for data
while(1)
<
printf(“Waiting for data…”);
fflush(stdout);
memset(buf,’\0′, BUFLEN); //Add this line
if that sent character, how about send some file, example a picture, how to change in the script character sent to picture sent.
Please remove gets in Client:46 with:
fgets(message, BUFLEN, stdin);
What if the data sent from client side having some different Server address, SERVER 192.168.16.30 (this IP is pingable)
how to pass array , vector etc. between client and server?
if ((recv_len = recvfrom(s, buf, BUFLEN, 0, (struct sockaddr *) &si_other, &slen)) == -1)
here &slen should be (socklen_t*)&slen . and work perfectly. Thank u
Источник
Клиент-Сервер Socket linux (Система обмена сообщениями)
Здравствуйте! Помогите,пожалуйста,доработать Клиент-Сервер.Никак не получается. Завтра последний день сдачи Условия выполнения: «Задание: разработать приложение-клиент и приложение сервер, обеспечивающие функции мгновенного обмена сообщений между пользователями.
Основные возможности. Серверное приложение должно реализовывать следующие функции: 1) Прослушивание определенного порта 2) Обработка запросов на подключение по этому порту от клиентов 3) Поддержка одновременной работы нескольких клиентов через механизм нитей 4) Передача текстового сообщения одному клиенту 5) Передача текстового сообщения всем клиентам 6) Прием и ретрансляция входящих сообщений от клиентов 7) Обработка запроса на отключение клиента 8) Принудительное отключение указанного клиента
Клиентское приложение должно реализовывать следующие функции: 1) Установление соединения с сервером 2) Передача сообщения всем клиентам 3) Передача сообщения указанному клиенту 4) Прием сообщения от сервера с последующей индикацией 5) Разрыв соединения 6) Обработка ситуации отключения клиента сервером
Настройки приложений. Разработанное клиентское приложение должно предоставлять пользователю настройку IP-адреса или доменного имени сервера сообщений и номера порта сервера. »
Пока в работе у меня выполнено следующие условия:Сервер:1,2,3 ;Клиент:1,. В данном случае у меня клиент отправляет сообщение серверу,а сервер отправляет этоже сообщение обратно клиенту.
Деревянные треды лора: помогите решить ДЗ
3) Поддержка одновременной работы нескольких клиентов через механизм нитей
Это делается через epoll, тащемта. Вот как-то так, наверно
Вот ещё пример, как работать со многими клиентами:
man select && man poll && man kqueue (через последнюю функцию сделан event-base в iolib)
fork() и указанные в ТЗ нити — мягко говоря разные вещи
и перед тем как начать списывать код из источников стоит набросать на бумажке протокол: какие и как данные ходят туда-сюда, форматы сообщений, состояния соединений.
fork() и указанные в ТЗ нити — мягко говоря разные вещи
А разве и то и другое не через clone() выполняется?
Еще вопросик:
Как сделать так,чтобы клиент мог скачать с сервера песню?Например формата .mp3
А у тебя по этому поводу свои мысли есть какие-нибудь? Мне просто интересно, есть ли у тебя мозг впринципе.
есть куча протоколов прикладного уровня. самое простое читать в стрим файл и send()/recv()
Возможно как то так: На сервере как то так: FILE * file; file = fopen(«test.mp3»,«wt»); после делаю send. Далее на клиента пишу recv . а вот дальше не знаю,куда записать эту песню и т.д.
Re: Еще вопросик:
Лучше воспользоваться более высокоуровневым протоколом. Хоть http.
Глянь сюда, например:
Далее на клиента пишу recv . а вот дальше не знаю,куда записать эту песню и т.д.
Также открываешь файл на запись и пишешь.
К сожалению по заданию нельзя
не могли бы написать пример в коде?
Нет, не хочу тратить время. Читай man’ы.
Ты делаешь recv из сокета в буфер, а потом write (man 2 write) из буфера в файл
писал прям тут, думаю суть понятна
есть опечатки сразу сам вижу.. но чет редактирование поста не доступно
Пару опечаток исправил,но не компилируется. gcc пишет:expected declaration of statement at and of intut.
Код: FILE* f = fopen(«music.mp3»,«rb»);
fseek (f , 0 , SEEK_END); int fsize = ftell (f); rewind (f);
long sended = 0; long readed = 0;
>while(sended ( 19.01.14 18:03:55 )
Пару опечаток исправил,но не компилируется. gcc пишет:expected declaration of statement at and of intut.
jo_b1ack,Спасибо тебе большое. Теперь дошло как это работает.
Осталось разбираться с системой обмена сообщений.
Мог ли бы еще помочь в одной проблемке?
У меня все передаётся,но после сервер и клиент просто висят.
Если я убираю while то передается только 4кб и идет дальше по коду т.е. не висит .
Как это исправить?
попробуй заменить в приеме строчку
на while(rcv_len > 0);
возможно после закрытия сокета recv возвращает не 0 — закрытие соединения, а SOCKET_ERROR
Пробовал,все также. В коде пробовал задать время на while ,но не очень успешно,закоментил .
у тебя в сервере 2 бесконечных цикла, и close(sock); после них.. ясное дело оно висит. бесконечные циклы это вообще зло.
К сожалению ,все равно висит. Убрал все while того где идет передача файла в сервере и клиенте
у тебя цикл начинается прям перед accept. поставь close(sock) после fclose(f); вприеме файла на сервере
Все заработало,в сервере написал так: >while(sended != fsize);
Убиваем ваш сервер. Нужно на сервере проверку ограничение на количество соединений поставить.
да там куча и маленькая тележка косяков.. в этом коде
Здравствуйте! Тоже начал писать сервер и клиент на чистом С, вы могли бы указать косяки, желательно куски проблемного кода, очень интересно. И немного оффтоп вопрос, в двух словах, какие есть пути импрува сервера/клиента ? Какие фичи еще допилить можно ? Пока есть идея сделать простой клиент/сервер и сниффер, который будет парсить передаваемые пакеты, также есть мысль добавить шифрование траффика и потом попытаться заточить под это свой сниффер. Естественно я нацелен писать велосипеды, ради изучения как языка С, так и сетевого программирования.
пиши и выкладывай на форум) думаю, обосрать тут все горазды что угодно 😉
Доброго времени суток. Подскажите, вы реализовали все задачи, которые перед вами стояли в этой теме? Не могли бы поделиться данной системой передачи сообщений? Спасибо.
Что, уже сессия началась?
Еще нет, а вот курсовые уже нужно сдавать. Может кто-нибудь сможет помочь или подтолкнуть в нужное русло. Вообщем задача поставлена так: «Сетевой чат (TCP)fork()»
Столкнулся вот с такой проблемой: Отправка, прием, обратная отправка сообщений — все реализовано. Для каждого клиента создается новый процесс и создается массив сокетов подключенных к серверу, который обрабатывается в этом процессе и отправляет данные всем имеющимся в массиве клиентам. При еще одном подключении, опять создается новый процесс, обновяется массив сокетов и т.д. Но у первого клиента массив сокетов не обновляется по понятным причинам. т.е. он работает со старой версией массива сокетов и не видит новых клиентов, которые подключились после него. Допустим подключено 3 клиента. Если сообщение отправит первый клиент, то сервер отправит сообщение только ему. т.к. у него в массиве хранится только он сам. Если отправит второй клиент сообщение, то сервер отправит обратно уже первому и второму клиенту. Если отправит третий клиент сообщение, то сервер обработает отправку и в первый и во второй и в третий клиент, т.к. он содержит в массиве все подключенные клиенты. Пробовал записывать в файл всех новых клиентов, и при обработке запроса, он считывает с файла сокеты и соответственно отправляет всем. Но тоже ничего не выходит. Считывать — считывает, но сообщения не доходят до клиента.
Есть решение этой проблемы? Спасибо.
А клиенты должны именно через выданный сокет работать? Т.е. все на одной машине? Как конкретно звучит задачка?
В твоей формулировке можно сделать так:
Завести shared memory и в ней хранить массив сокетов. Естественно размер массива задан статически. И стоит серелиазовать доступ к массиву (например мютексом).
Или использовать PF_UNIX сокеты и хранить их в определенном месте на диске.
В задаче ничего про сокеты не сказано. А сформулирована задача следующим образом. Реализовать клиент-сервер программу для передачи сообщений. Использовать TCP протокол и fork().
Т.е. реализовать чат один ко многим через TCP и fork. Будет огромным плюсом, если добавить приватный чат (один к одному)
А разве есть большая разница, если не на одной машине? Если на разных машинах клиент и сервер, то ведь клиенту всего-лишь нужно указать адрес и порт куда подключаться. Или я ошибаюсь и есть большая разница? В любом случае демонстрировать я буду на одной машине, но интересно, неужели есть большая разница.
Спасибо за подсказку. Надо попробовать с разделяемой памятью. А почему не работает обычное сохранение сокетов в файл? Ведь файл все время обновляется, сервер имеет к нему доступ, там хранятся все подключенные клиенты. Но вот сообщение не отправляет на клиенты, которые были подключены после клиента, который отправляет сообщение.
Я тебе неправильно сказал, насчет шаред мемори. Будет точно такая же проблема, т.к. это файловый дескриптор. При форке наследуются открытые дескрипторы, но дескриптор следующего наследника уже будет не валиден.
Надо каждому процессу выдать по уникальному порту, который потом он будет слушать. При этом сохранить все используемые порты в определенный файлик. Соотвественно, после форка каждый процесс открывает сокет. И по команде будет подключаться и слать сообщения другим клентам.
Как я понимаю, у каждого процесса есть свой порт, его и надо использовать. Он узнается с помощью getpid(); После вызова форка, я записываю порт в файл, вызывается функция где должно рассылаться наше сообщение. Там я считываю все порты, а что с ними делать дальше? Как прикрутить к рассылке. Я отправляю функцией sendto, где в параметрах указывается (номер сокета,сообщение, размер сообщения и т.д.) Вот раньше я сохранял номера сокетов и спокойно отправлял, но с известной проблемой. А что делать с портом? Как его прикрутить к отправке сообщений? Спасибо.
Вот класический пример tcp клиент/сервера
Тут два разных процесса идет: создание серверного сокета для приема соединений. И создание сокета, для соединения с сервером. В твоем случае можно основной процесс сделать в виде сервера, а дочерние — подключенными к нему клиентами.
Запись и чтение можно делать при помощи read/write.
getpid возвращает пид процесса, с номером порта не связанно.
Источник