Differences
This shows you the differences between two versions of the page.
workshop:sockets [2010-09-29 19:59] equinox |
workshop:sockets [2015-09-16 12:41] |
||
---|---|---|---|
Line 1: | Line 1: | ||
- | ====== Vortrag/Workshop Einführung in Unix Socket Programmierung ====== | ||
- | |||
- | * by Christian Pointner | ||
- | |||
- | |||
- | |||
- | |||
- | ===== Beispielcode ===== | ||
- | |||
- | Es folgen ein paar simple Beispielprogramme die die Verwendung von Sockets unter Unix zeigen. Alle Beispiele und ein kleines Makefile können auch direkt per unten stehendem Link heruntergeladen werden: | ||
- | |||
- | {{workshops:socket-examples.tar.gz|socket-examples.tar.gz}} | ||
- | |||
- | Es folgt noch der Code für einen sehr simplen Chat Server anhand dessen die Verwendung des Resolvers (DNS etc.) gezeigt wird. | ||
- | |||
- | ==== Beispiel: udpclient ==== | ||
- | |||
- | <file> | ||
- | /* | ||
- | * udpclient | ||
- | * | ||
- | * This is a very basic UDP client example to show the usage of | ||
- | * sockets. | ||
- | * | ||
- | * Copyright (C) 2010 Christian Pointner <equinox@realraum.at> | ||
- | * | ||
- | * udpclient is free software: you can redistribute it and/or modify | ||
- | * it under the terms of the GNU General Public License as published by | ||
- | * the Free Software Foundation, either version 3 of the License, or | ||
- | * any later version. | ||
- | * | ||
- | * udpclient is distributed in the hope that it will be useful, | ||
- | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
- | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
- | * GNU General Public License for more details. | ||
- | * | ||
- | * You should have received a copy of the GNU General Public License | ||
- | * along with udpclient. If not, see <http://www.gnu.org/licenses/>. | ||
- | */ | ||
- | |||
- | #include <stdio.h> | ||
- | #include <stdlib.h> | ||
- | #include <unistd.h> | ||
- | #include <errno.h> | ||
- | #include <string.h> | ||
- | |||
- | #include <sys/types.h> | ||
- | #include <sys/socket.h> | ||
- | |||
- | #include <arpa/inet.h> | ||
- | |||
- | int main(int argc, char** argv) | ||
- | { | ||
- | if(argc <= 2) { | ||
- | fprintf(stderr,"too few arguments\n"); | ||
- | exit(1); | ||
- | } | ||
- | printf("starting UDP Client\n"); | ||
- | |||
- | int sock = socket(AF_INET, SOCK_DGRAM, 0); | ||
- | if(sock < 0) { | ||
- | perror("socket() call failed"); | ||
- | exit(-1); | ||
- | } | ||
- | | ||
- | struct sockaddr_in local_addr; | ||
- | memset((char *) &local_addr, 0, sizeof(local_addr)); | ||
- | local_addr.sin_family = AF_INET; | ||
- | local_addr.sin_port = htons(4321); | ||
- | local_addr.sin_addr.s_addr = htonl(INADDR_ANY); | ||
- | |||
- | if(bind(sock, (struct sockaddr *)&local_addr, sizeof(local_addr))==-1) { | ||
- | perror("bind() call failed"); | ||
- | exit(-1); | ||
- | } | ||
- | |||
- | struct sockaddr_in remote_addr; | ||
- | int alen, len; | ||
- | alen = sizeof(remote_addr); | ||
- | remote_addr.sin_family = AF_INET; | ||
- | remote_addr.sin_port = htons(atoi(argv[2])); | ||
- | if (inet_aton(argv[1], &remote_addr.sin_addr)==0) { | ||
- | perror("inet_aton() call failed"); | ||
- | exit(-1); | ||
- | } | ||
- | |||
- | uint8_t buffer[1500]; | ||
- | for (;;) { | ||
- | if((len = read(0, buffer, 1500))==-1) { | ||
- | perror("read() call failed"); | ||
- | exit(-1); | ||
- | } | ||
- | |||
- | if((len = sendto(sock, buffer, len, 0, (struct sockaddr *)&remote_addr, alen))==-1) { | ||
- | perror("sendto() call failed"); | ||
- | exit(-1); | ||
- | } | ||
- | } | ||
- | |||
- | close(sock); | ||
- | | ||
- | printf("exiting UDP Client\n"); | ||
- | |||
- | return 0; | ||
- | } | ||
- | </file> | ||
- | ==== Beispiel: udpserver ==== | ||
- | |||
- | <file> | ||
- | /* | ||
- | * udpserver | ||
- | * | ||
- | * This is a very basic UDP client example to show the usage of | ||
- | * sockets. | ||
- | * | ||
- | * Copyright (C) 2010 Christian Pointner <equinox@realraum.at> | ||
- | * | ||
- | * udpserver is free software: you can redistribute it and/or modify | ||
- | * it under the terms of the GNU General Public License as published by | ||
- | * the Free Software Foundation, either version 3 of the License, or | ||
- | * any later version. | ||
- | * | ||
- | * udpserver is distributed in the hope that it will be useful, | ||
- | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
- | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
- | * GNU General Public License for more details. | ||
- | * | ||
- | * You should have received a copy of the GNU General Public License | ||
- | * along with udpserver. If not, see <http://www.gnu.org/licenses/>. | ||
- | */ | ||
- | |||
- | #include <stdio.h> | ||
- | #include <stdlib.h> | ||
- | #include <unistd.h> | ||
- | #include <errno.h> | ||
- | #include <string.h> | ||
- | |||
- | #include <sys/types.h> | ||
- | #include <sys/socket.h> | ||
- | |||
- | #include <arpa/inet.h> | ||
- | |||
- | int main(int argc, char** argv) | ||
- | { | ||
- | printf("starting UDP Server\n"); | ||
- | |||
- | int sock = socket(AF_INET, SOCK_DGRAM, 0); | ||
- | if(sock < 0) { | ||
- | perror("socket() call failed"); | ||
- | exit(-1); | ||
- | } | ||
- | | ||
- | struct sockaddr_in local_addr; | ||
- | memset((char *) &local_addr, 0, sizeof(local_addr)); | ||
- | local_addr.sin_family = AF_INET; | ||
- | local_addr.sin_port = htons(1234); | ||
- | local_addr.sin_addr.s_addr = htonl(INADDR_ANY); | ||
- | |||
- | if(bind(sock, (struct sockaddr *)&local_addr, sizeof(local_addr))==-1) { | ||
- | perror("bind() call failed"); | ||
- | exit(-1); | ||
- | } | ||
- | |||
- | struct sockaddr_in remote_addr; | ||
- | int alen, len; | ||
- | alen = sizeof(remote_addr); | ||
- | uint8_t buffer[1500]; | ||
- | for (;;) { | ||
- | if((len = recvfrom(sock, buffer, 1500, 0, (struct sockaddr *)&remote_addr, &alen))==-1) { | ||
- | perror("recvfrom() call failed"); | ||
- | exit(-1); | ||
- | } | ||
- | |||
- | printf("Received %d Bytes from %s:%d\n", len, inet_ntoa(remote_addr.sin_addr), ntohs(remote_addr.sin_port)); | ||
- | } | ||
- | |||
- | close(sock); | ||
- | | ||
- | printf("exiting UDP Server\n"); | ||
- | |||
- | return 0; | ||
- | } | ||
- | </file> | ||
- | |||
- | ==== Beispiel: tcpclient ==== | ||
- | |||
- | <file> | ||
- | /* | ||
- | * tcpclient | ||
- | * | ||
- | * This is a very basic TCP client example to show the usage of | ||
- | * sockets. | ||
- | * | ||
- | * Copyright (C) 2010 Christian Pointner <equinox@realraum.at> | ||
- | * | ||
- | * tcpclient is free software: you can redistribute it and/or modify | ||
- | * it under the terms of the GNU General Public License as published by | ||
- | * the Free Software Foundation, either version 3 of the License, or | ||
- | * any later version. | ||
- | * | ||
- | * tcpclient is distributed in the hope that it will be useful, | ||
- | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
- | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
- | * GNU General Public License for more details. | ||
- | * | ||
- | * You should have received a copy of the GNU General Public License | ||
- | * along with tcpclient. If not, see <http://www.gnu.org/licenses/>. | ||
- | */ | ||
- | |||
- | #include <stdio.h> | ||
- | #include <stdlib.h> | ||
- | #include <unistd.h> | ||
- | #include <errno.h> | ||
- | #include <string.h> | ||
- | |||
- | #include <sys/types.h> | ||
- | #include <sys/socket.h> | ||
- | |||
- | #include <arpa/inet.h> | ||
- | |||
- | int main(int argc, char** argv) | ||
- | { | ||
- | if(argc <= 2) { | ||
- | fprintf(stderr,"too few arguments\n"); | ||
- | exit(1); | ||
- | } | ||
- | printf("starting TCP Client\n"); | ||
- | |||
- | int sock = socket(AF_INET, SOCK_STREAM, 0); | ||
- | if(sock < 0) { | ||
- | perror("socket() call failed"); | ||
- | exit(-1); | ||
- | } | ||
- | | ||
- | struct sockaddr_in remote_addr; | ||
- | remote_addr.sin_family = AF_INET; | ||
- | remote_addr.sin_port = htons(atoi(argv[2])); | ||
- | if (inet_aton(argv[1], &remote_addr.sin_addr)==0) { | ||
- | perror("inet_aton() call failed"); | ||
- | exit(-1); | ||
- | } | ||
- | |||
- | if(connect(sock, (struct sockaddr *)&remote_addr, sizeof(remote_addr))==-1) { | ||
- | perror("connect() call failed"); | ||
- | exit(-1); | ||
- | } | ||
- | |||
- | int len; | ||
- | uint8_t buffer[1500]; | ||
- | for (;;) { | ||
- | if((len = read(0, buffer, 1500))==-1) { | ||
- | perror("read() call failed"); | ||
- | exit(-1); | ||
- | } | ||
- | |||
- | int offset = 0; | ||
- | int wlen; | ||
- | for(;;) { | ||
- | wlen = send(sock, &buffer[offset], len - offset, 0); | ||
- | if(wlen == -1) { | ||
- | if(errno != EINTR) { | ||
- | perror("write() call failed"); | ||
- | exit(-1); | ||
- | } | ||
- | wlen = 0; | ||
- | } | ||
- | |||
- | offset += wlen; | ||
- | if(offset+1 >= len) | ||
- | break; | ||
- | } | ||
- | } | ||
- | |||
- | close(sock); | ||
- | | ||
- | printf("exiting TCP Client\n"); | ||
- | |||
- | return 0; | ||
- | } | ||
- | </file> | ||
- | |||
- | ==== Beispiel: tcpserver ==== | ||
- | |||
- | <file> | ||
- | /* | ||
- | * tcpserver | ||
- | * | ||
- | * This is a very basic TCP server example to show the usage of | ||
- | * sockets. | ||
- | * | ||
- | * Copyright (C) 2010 Christian Pointner <equinox@realraum.at> | ||
- | * | ||
- | * tcpserver is free software: you can redistribute it and/or modify | ||
- | * it under the terms of the GNU General Public License as published by | ||
- | * the Free Software Foundation, either version 3 of the License, or | ||
- | * any later version. | ||
- | * | ||
- | * tcpserver is distributed in the hope that it will be useful, | ||
- | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
- | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
- | * GNU General Public License for more details. | ||
- | * | ||
- | * You should have received a copy of the GNU General Public License | ||
- | * along with tcpserver. If not, see <http://www.gnu.org/licenses/>. | ||
- | */ | ||
- | |||
- | #include <stdio.h> | ||
- | #include <stdlib.h> | ||
- | #include <unistd.h> | ||
- | #include <errno.h> | ||
- | #include <string.h> | ||
- | |||
- | #include <sys/types.h> | ||
- | #include <sys/socket.h> | ||
- | |||
- | #include <arpa/inet.h> | ||
- | |||
- | int main(int argc, char** argv) | ||
- | { | ||
- | printf("starting TCP Server\n"); | ||
- | |||
- | int server = socket(AF_INET, SOCK_STREAM, 0); | ||
- | if(server < 0) { | ||
- | perror("socket() call failed"); | ||
- | exit(-1); | ||
- | } | ||
- | | ||
- | struct sockaddr_in local_addr; | ||
- | memset((char *) &local_addr, 0, sizeof(local_addr)); | ||
- | local_addr.sin_family = AF_INET; | ||
- | local_addr.sin_port = htons(1234); | ||
- | local_addr.sin_addr.s_addr = htonl(INADDR_ANY); | ||
- | |||
- | if(bind(server, (struct sockaddr *)&local_addr, sizeof(local_addr))==-1) { | ||
- | perror("bind() call failed"); | ||
- | exit(-1); | ||
- | } | ||
- | |||
- | if(listen(server, 5)==-1) { | ||
- | perror("listen() call failed"); | ||
- | exit(-1); | ||
- | } | ||
- | |||
- | fd_set readfds, tmpfds; | ||
- | FD_ZERO(&readfds); | ||
- | FD_SET(server, &readfds); | ||
- | int max_fd = server; | ||
- | uint8_t buffer[1500]; | ||
- | struct sockaddr_in remote_addr; | ||
- | int alen, len; | ||
- | for (;;) { | ||
- | memcpy(&tmpfds, &readfds, sizeof(tmpfds)); | ||
- | int num = select(max_fd+1, &tmpfds, NULL, NULL, NULL); | ||
- | if(num == -1 && errno != EINTR) { | ||
- | perror("select() call failed"); | ||
- | exit(-1); | ||
- | } | ||
- | if(num == -1 || !num) | ||
- | continue; | ||
- | |||
- | if(FD_ISSET(server, &tmpfds)) { | ||
- | int new_client = accept(server, (struct sockaddr *)&remote_addr, &alen); | ||
- | if(new_client==-1) { | ||
- | perror("accept() call failed"); | ||
- | exit(-1); | ||
- | } | ||
- | printf("new connection %s:%d (fd=%d)\n", inet_ntoa(remote_addr.sin_addr), ntohs(remote_addr.sin_port), new_client); | ||
- | FD_SET(new_client, &readfds); | ||
- | max_fd = (max_fd < new_client) ? new_client : max_fd; | ||
- | FD_CLR(server, &tmpfds); | ||
- | } | ||
- | |||
- | int fd; | ||
- | for(fd=0; fd<=max_fd; ++fd) { | ||
- | if(FD_ISSET(fd, &tmpfds)) { | ||
- | len = recv(fd, buffer, 1500, 0); | ||
- | if(len <= 0) { | ||
- | if(len < 0) perror("recv() call failed"); | ||
- | else fprintf(stderr, "client closed connection\n"); | ||
- | | ||
- | printf("removing client (fd=%d)\n", fd); | ||
- | FD_CLR(fd, &readfds); | ||
- | close(fd); | ||
- | } | ||
- | else | ||
- | printf("Received %d Bytes from client (fd=%d)\n", len, fd); | ||
- | } | ||
- | } | ||
- | } | ||
- | |||
- | close(server); | ||
- | | ||
- | printf("exiting TCP Server\n"); | ||
- | |||
- | return 0; | ||
- | } | ||
- | </file> | ||
- | |||
- | |||
- | ---- | ||
- | {{tag>workshop}} | ||
realraum Graz, Brockmanngasse 15, 8010 Graz, realraum - Verein für Technik in Kultur und Gesellschaft