linux network programming
1, socket
1. Detailed explanation of common functions
1.establish socket: int socket(int domain, int type, int protocol); domain: AF_INET This is most used to generate socket Protocol, use TCP or UDP To transmit, use IPv4 Address of AF_INET6 Similar to the above, but for use IPv6 Address of AF_UNIX Local agreement type:SOCK_STREAM This protocol is a sequential, reliable and data complete connection based on byte stream. This is one of the most used socket Type, this socket Is to use TCP For transmission. SOCK_DGRAM This protocol is a connectionless, fixed length transmission call. The protocol is unreliable to use UDP To connect it protocol: Passing 0 means using the default protocol. protcol Is 0, according to type Select the appropriate protocol. When type yes sock_stream Time. protoc yes tcp When type yes sock_dgram Time.protcol yes udp Success: returns a pointer to the newly created socket File descriptor, failed: Return-1,set up errno 2.binding socket Ports and ip Int bind(int sockfd,const struct sockaddr*addr,socklen_t addrlen); sockfd: Socket fd(File descriptor), socket()Return value of function addr: structural morphology ip+port(Port) struct sockaddr_in{ (Involving coercion sockaddr_in ->sockaddr (Reference) short int sin_family; //Address family unsigned short int sin_port; //Port number struct in_addr sin_addr; //IP address } struct in_addr { __be32 s_addr; }; 3.set up sockefd Maximum number of simultaneous links int listen(int sockfd,int backlog); backlog: Maximum number of requests to link client queues Return value: judge success or failure 4.Wait for a sockfd Client response for int accept(int sockfd,struct sockaddr*addr,socklen_t*addrlen) addr: Outgoing parameters: the structure of the client to which I am connected (including the client) ip+Port) Return value: the socket connecting the client. When there is one client response listenfd When, accept Will return a connfd Communicate with clients. 5.client And server signal communication int connect(int sockfd,struct sockaddr*serv_addr,int addrlen) sockfd: Pass in parameters and file descriptors to bind the server socket with successful connection, so as to facilitate the connection to the server at the client IO operation serv_addr: Bind the structure of the server I want to link (need to initialize binding) ip And fracture), indicating the purpose
2. Server code
Idea: use socket to create a listenfd, bind its server ip and port, set its maximum communication number, accept blocks listening, and when there is a client response, accept returns a connfd to communicate with the client. Listenfd is always used as the swap in parameter of accept to listen to the client. Whenever a client passes through it, a new connfd tone communication is set. It is equivalent to that connfd is the fd that binds the client ip and port. The server can communicate with connfd only by reading and writing connfd.
Single process server #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <stdio.h> #include <string.h> #include <stdlib.h> #include <unistd.h> #define SER_PORT 8000 int main(void) { int sockfd,connfd;// int len; char wbuf[1024]; char rbuf[1024]; struct sockaddr_in serveraddr,clientaddr; //Two structures: one is used to bind the identity to the socket, and the other is used to receive the structure of the customer service end //1. Create a listening socket sockfd = socket(AF_INET,SOCK_STREAM,0); //2.bind (socket is required for communication to bind the home address and house number to ip and port) bzero(&serveraddr,sizeof(serveraddr)); //Similar to memset emptying structure //Address family protocol, select IPV4 serveraddr.sin_family = AF_INET; //Is it ipv4 or ipv6 //IP address any available IP address of the machine serveraddr.sin_addr.s_addr = htonl(INADDR_ANY); serveraddr.sin_port = htons(SER_PORT);//Port number bind(sockfd,(struct sockaddr *)&serveraddr,sizeof(serveraddr)); //3. Sum of listening and server connection listen(sockfd,128); int size = sizeof(clientaddr); //4.accept blocks the request to listen to the customer service link connfd = accept(sockfd,(struct sockaddr *)&clientaddr,&size); //Output ip and port of customer service terminal char ipstr[128]; printf("client ip%s ,port %d\n",inet_ntop(AF_INET,&clientaddr.sin_addr.s_addr,ipstr,sizeof(ipstr)), ntohs(clientaddr.sin_port)); //5. Processing client requests //Reading and writing while(1) { memset(wbuf,0,sizeof(wbuf));//empty memset(rbuf,0,sizeof(wbuf)); //receive messages int len = read(connfd,rbuf,sizeof(rbuf)); if(len==0)//Indicates disconnection { printf("client is close....\n"); } printf("receive from client:%s",rbuf); //send message printf("send to client:"); fgets(wbuf,sizeof(wbuf),stdin); write(connfd,wbuf,strlen(wbuf)); } close(connfd); close(sockfd); return 0; } Multi process server #include <stdio.h> #include <string.h> #include <netinet/in.h> #include <arpa/inet.h> #include <signal.h> #include <sys/wait.h> #include <ctype.h> #include <unistd.h> #include "wrap.h" #define MAXLINE 8192 #define SERV_PORT 8000 void do_sigchild(int num) { while (waitpid(0, NULL, WNOHANG) > 0) ; } int main(void) { struct sockaddr_in servaddr, cliaddr; socklen_t cliaddr_len; int listenfd, connfd; char buf[MAXLINE]; char str[INET_ADDRSTRLEN]; int i, n; pid_t pid; struct sigaction newact; newact.sa_handler = do_sigchild; sigemptyset(&newact.sa_mask); newact.sa_flags = 0; sigaction(SIGCHLD, &newact, NULL); listenfd = Socket(AF_INET, SOCK_STREAM, 0); int opt = 1; setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)); bzero(&servaddr, sizeof(servaddr)); servaddr.sin_family = AF_INET; servaddr.sin_addr.s_addr = htonl(INADDR_ANY); servaddr.sin_port = htons(SERV_PORT); Bind(listenfd, (struct sockaddr *)&servaddr, sizeof(servaddr)); Listen(listenfd, 20); printf("Accepting connections ...\n"); while (1) { cliaddr_len = sizeof(cliaddr); connfd = Accept(listenfd, (struct sockaddr *)&cliaddr, &cliaddr_len); printf("-------------------------%d\n", connfd); pid = fork(); if (pid == 0) { Close(listenfd); while (1) { n = Read(connfd, buf, MAXLINE); if (n == 0) { printf("the other side has been closed.\n"); break; } printf("received from %s at PORT %d\n", inet_ntop(AF_INET, &cliaddr.sin_addr, str, sizeof(str)), ntohs(cliaddr.sin_port)); for (i = 0; i < n; i++) buf[i] = toupper(buf[i]); Write(STDOUT_FILENO, buf, n); Write(connfd, buf, n); } Close(connfd); return 0; } else if (pid > 0) { Close(connfd); } else perr_exit("fork"); } return 0; }
3. Client code
Code idea: create connfd and call connect to communicate with the ip and port of the server. It is worth noting that connfd can be bound to the ip and port of the client without using bind. It will be bound automatically when calling connect.
#include <sys/types.h> /* See NOTES */ #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <stdio.h> #include <string.h> #include <stdlib.h> #include <unistd.h> #define SER_PORT 8000 int main(void) { int sockfd; struct sockaddr_in serveraddr; int len; char wbuf[1024],rbuf[1024]; //1. Socket communication socket, create a sockfd sockfd = socket(AF_INET,SOCK_STREAM,0); char ipstr[]="127.0.0.1"; //2. Edit the server address to which you want to connect and bind bzero(&serveraddr,sizeof(serveraddr)); serveraddr.sin_family = AF_INET; //Set address family protocol serveraddr.sin_port = htons(SER_PORT); //Set port number inet_pton(AF_INET,ipstr,&serveraddr.sin_addr.s_addr);//Set the ip address point division decimal to network byte order //2. connect server sockfd outgoing server socket connect(sockfd,(struct sockaddr*)&serveraddr,sizeof(serveraddr)); //3. Reading and writing while(1) { memset(wbuf,0,sizeof(wbuf)); memset(rbuf,0,sizeof(rbuf)); //send message printf("send to server:"); fgets(wbuf,sizeof(wbuf),stdin); write(sockfd,wbuf,strlen(wbuf)); //receive messages len=read(sockfd,rbuf,sizeof(rbuf)); if(len==0)//Indicates disconnection { printf("server is close....\n"); } printf("receive from server:%s",rbuf); } //4,close close(sockfd); return 0; }
2, select
1. Concept of IO multiplexing
In the socket model, we block listening fd to block the process in accept. IO reuse means that the non blocking loop listens to connfd and listenfd in the server. When fd is ready and the process runs to the non blocking loop listening function, it will run the response program.
Multiplexing IO is to use one thread to listen to multiple IO requests at the same time and return when there are IO requests. Note that although our IO multiplexing will also be blocked, the blocking here is at the application level, that is, blocking in the multiplexing method, not at the operating system level.
2. Detailed explanation of common functions
1.int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout); nfds: The total number of file descriptors listened on, which will be 1 greater than the maximum value of the file descriptor table in the file descriptor table set, because the file descriptors count from 0 readfds: The set of file descriptors for the readable events to be monitored (if there is any movement, the set will only retain the generated readable events). See the following example writefds: Set of file descriptors of writable events to listen for exceptfds: Set of file descriptors of the exception events to listen for timeout: That is, tell the kernel select Give up waiting after waiting for how long. Generally set as NULL It means blocking and waiting without movement 2.set Correlation function, set Is an array of 1024, which can record each fd. FD_ZERO(fd_set* set) Understood as initialization file descriptor geometry (Set all bits to 0) FD_SET(fd,fd_set* set) Add file descriptor to collection(Correspondence in essence fd Bit set to 1) FD_CLR(fd,fd_set* set) It is understood as taking the file descriptor out of the collection (essentially corresponding) fd (bit set to 0) FD_ISSET(fd,fd_set* set) It is understood to detect whether the modified file descriptor is in the set (essentially corresponding) fd Whether the bit is set to 1)
3. Server code
Code idea: create listenfd and place it in the fd collection set, call select blocking listener set set, when select returns, judge whether there is listenfd in set, if there is, there is new client to communicate with server, call accept to return to client and port and get a new one, put it in the middle. Continue to block the set listening to the select. If the returned set has listenfd, call accept to add the connfd of the new client to the set. If the returned set has connfd, communicate with the corresponding client.
#include <unistd.h> #include <stdlib.h> #include <string.h> #include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <errno.h> #include <termios.h> #include <signal.h> #include <sys/types.h> /* See NOTES */ #include <sys/socket.h> #include <arpa/inet.h> #define SET_PORT 8000 int main(int argc, char *argv[]) { int sockfd,connfd;//Listen socket and connect socket struct sockaddr_in serveraddr; int i;//It is mainly used for i of various for loops int on = 1;//Only the reusable ports set below can be used //1. Create a listening socket sockfd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) ;//Set as reusable port //2.bind (socket is required for communication. I'll tie my home address and house number to ip and port) serveraddr.sin_family = AF_INET; serveraddr.sin_port = htons(SET_PORT); serveraddr.sin_addr.s_addr = htonl(INADDR_ANY); bind(sockfd, (struct sockaddr *)&serveraddr,sizeof(serveraddr)); //3. Sum of listening and server connection listen(sockfd,128) ; int maxfd = sockfd; //Initializes two collections and an array int client[FD_SETSIZE];//The array is used to store the fd circular query of the customer service side_ SetSize is a macro with a maximum of 1024 by default fd_set rset;//Put it in the select, and there is always one fd in the set fd_set allset;//Add fd only FD_ZERO(&rset);//Empty action FD_ZERO(&allset);//Empty action //Put the listening socket into FD_SET(sockfd,&allset); int nready; //Initialization arrays are all - 1. Expected identifier, starting from 0 for(i = 0; i < FD_SETSIZE; i++) client[i] = -1; while(1) { //A crucial step rset = allset;//Ensure that the select loop can listen to all file descriptors every time, because there will only be dynamic ones left in rset nready = select(maxfd+1,&rset,NULL,NULL,NULL);//Parameter one //New client if(FD_ISSET(sockfd,&rset)) { struct sockaddr_in clientaddr; memset(&clientaddr,0,sizeof(clientaddr)); int len = sizeof(clientaddr); connfd = accept(sockfd, (struct sockaddr*)&clientaddr,&len); char ipstr[128];//Used for printing printf("client ip%s ,port %d\n",inet_ntop(AF_INET,&clientaddr.sin_addr.s_addr,ipstr,sizeof(ipstr)), ntohs(clientaddr.sin_port)); //One thing to do: put the file df into the array for(i = 0; i < FD_SETSIZE; i++) { if(client[i] < 0) { client[i] = connfd; break;//Be sure to jump out of the error prone point in time } } //The second thing to do: put it into the collection FD_SET(connfd,&allset);//Put into collection //Prevent out of range / / the first parameter of select must be the monitored file descriptor + 1. If there are new client connections and the maximum value is getting larger and larger, it will be assigned if(connfd > maxfd) maxfd = connfd; //The following indicates that if there is only one movement at the same time, there is no need to enter the lower else judgment processing. If there is more than one nready-1, enter the lower judgment again if(--nready <= 0) continue; } else { //Connected FD generates readable event for(i = 0; i < FD_SETSIZE; i++)//FD_SEISIZE is the macro 1024 / / loop to get the element comparison from the array { if(FD_ISSET(client[i],&rset)) { connfd = client[i]; char buf[1024] = {0}; int nread ; nread = read(connfd, buf, sizeof(buf)); if(nread == 0)//Indicates that the customer service end is disconnected { //Four step processing print description delete from set delete from array close customer service end printf("client is close..\n"); FD_CLR(connfd, &allset); client[i] = -1; close(connfd); } else//Normal read processing { write(connfd,buf,nread); memset(buf,0,1024); } //The following indicates that if the time is agreed, if there is only one readable event, there is no need to cycle the array elements and jump out directly //Don't waste time by letting the cycle go if(--nready <= 0) break; } } } } return 0; }
III epool
1. The difference between epool and select
epoll does not exist for the set_ Create will return an fd indicating that the space contains all the events (structures)
epoll packages every fd to be monitored into an event, and records this event in epollfd for epollfd to monitor
select generates movement, right? fd is put into the set, but epoll passes epoll_wait puts the events wrapped by the fd that generates the dynamic and static into the structure array
select needs to be backed up and the array needs to be recreated for fd cyclic comparison. epoll can obtain fd directly through packaged events (structures), and the efficiency is faster (the difference is mainly reflected in this)
The difference between the two is that select is suitable for the situation where there are few customer service clients, while epoll has no upper limit of clients
2. Common functions
#include <sys/epoll.h> int epoll_create(int size); Function: create a epoll Handle, which tells him the number of sockets that need to be monitored (it can also be understood as applying for a space to store the monitored socket) int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event); Function: control a epoll Events on the monitored file descriptor: registration, modification and deletion (that is, adding, deleting and modifying an event) int epoll_wait(int epfd,struct epoll_event * events,int maxevents,int timeout) Function: monitor the events on the red black tree and put the events that generate movement on the event In this array, int epoll_create(int size); Parameter 1: notify kernel to listen size individual fd,It is only a recommended value and has something to do with the hardware. (from Linux Kernel 2.6.8 From version, size This parameter is ignored and only requires size Greater than 0) Return value: Return epoll Handle( fd) int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event); Parameter 1: int epfd:epoll_create()Return value of Parameter 2: int op: Represents an action, represented by three macros EPOLL_CTL_ADD(Register new fd reach epfd) EPOLL_CTL_MOD(Modify registered fd Listening events) EPOLL_CTL_DEL(from epfd Delete a fd) Parameter 3: int fd Operation object( socket) Parameter 4: struct epoll_evevt* evevt; Tell the kernel what events to listen for int epoll_wait(int epfd,struct epoll_event * events,int maxevents,int timeout) Parameter 1: int epfd:epoll_create()Function return value Parameter 2: struct epoll_events* events An array used to pass back the processing events (that is, to store the events that generate movement) Parameter three:int maxevents Tell the kernel how many events are generated at most at the same time events The value must be greater than 0 Parameter four:int timeout express -1 Equivalent to blocking, 0 equivalent to non blocking, timeout(Unit: ms) Return value: the number of dynamic and static events successfully returned struct epoll_event { __uint32_t events; Macro definition read and write EPOLLIN read EPOLLOUT,Edge trigger EPOLLET epoll_data_t data; Consortium }; The consortium is as follows: typedef union epoll_data { void *ptr;//This pointer can point to a structure with a function. When a corresponding event occurs, the function in the structure pointed to by the secondary pointer can be called manually. This is the reactor model. int fd; //Generally, this fd determines whether it is the corresponding listenfd or connfd to determine whether there is a new client link and which old client is sending data __uint32_t u32; __uint64_t u64; } epoll_data_t; Edge Triggered (ET) Edge trigger is triggered only when data arrives, regardless of whether there is data in the cache. Level Triggered (LT) Horizontal trigger will be triggered as long as there is data
3. Service area code
Code idea: epool_create creates a red black tree, returns epollfd and points to the red black tree. Set the event structure of listenfd and call epool_ctl will listen fd to the tree, epool_wait monitors fd and epool on the tree_ When there is a response to wait, use epool_ Outgoing parameter struct epoll of wait_ Event * Events Check fd. If listenfd in events indicates that a new client communicates with the server, then call accept to get the ip and port of connfd and client, and upload the new connfd to the tree, and then listen to the red black tree. When there is an old client communicating, use connfd to communicate with it.
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <netinet/in.h> #include <arpa/inet.h> #include <sys/epoll.h> #include <errno.h> #include <string.h> #include <stdio.h> #include <unistd.h> #define MAXLINE 80 #define SERV_PORT 8000 / / port number #define OPEN_MAX 1024 / / maximum connections int main(int argc,char *argv[]) { int maxi,sockfd,connfd;//sockfd is used to listen to the connection socket used by connfd. To listen to the socket, you need to create a connection socket and wait for it to return. Socket is not required int nready,efd; //efd is the dynamic and static number generated by epoll model identifier nready struct sockaddr_in clientaddr, serveraddr; struct epoll_event event, events[OPEN_MAX]; //One fruit basket, one structure sockfd = socket(AF_INET, SOCK_STREAM, 0); bzero(&serveraddr, sizeof(serveraddr)); bzero(&clientaddr, sizeof(clientaddr)); serveraddr.sin_family = AF_INET; serveraddr.sin_addr.s_addr = htonl(INADDR_ANY); serveraddr.sin_port = htons(SERV_PORT); int on =1; setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) ;//Set as reusable port bind(sockfd, (struct sockaddr *) &serveraddr, sizeof(serveraddr)); listen(sockfd, OPEN_MAX);//Server Socket efd=epoll_create(OPEN_MAX); /*Wrapper server fd is an event*/ event.events=EPOLLIN|EPOLLET; event.data.fd=sockfd; epoll_ctl(efd,EPOLL_CTL_ADD,sockfd,&event);//Wrap the server fd as an event and put it on the red black tree while(1) { //Parameter 1 epollfd parameter 2 array of structures generating dynamic and static parameters parameter 3 maximum number of dynamic and static parameters generated at the same time nready=epoll_wait(efd,events,OPEN_MAX,-1);//The return value is the dynamic and static quantity for(int i=0;i<nready;i++) { if(!(events[i].events & EPOLLIN))//It is judged that the readable event does not return the loop immediately, which is different from select continue; if (events[i].data.fd==sockfd)//Indicates a new connection { int len=sizeof(clientaddr); char ipstr[128];//Used for printing connfd=accept(sockfd,(struct sockaddr *)&clientaddr,&len); printf("client ip%s ,port %d\n",inet_ntop(AF_INET,&clientaddr.sin_addr.s_addr,ipstr,sizeof(ipstr)), ntohs(clientaddr.sin_port)); event.events = EPOLLIN|EPOLLET; event.data.fd = connfd; epoll_ctl(efd, EPOLL_CTL_ADD, connfd, &event); } else//Indicates that the old data generates a readable event (1 data sent by the client 2 client disconnects) { connfd=events[i].data.fd; char buf [1024]; memset(buf,0,1024); int nread; nread=read(connfd,buf,sizeof(buf)); if(nread==0) { printf("client is close..\n"); //Print epoll_ctl(efd, EPOLL_CTL_DEL, connfd, NULL);//Delete select is to delete from the collection and array close(connfd);//Closing the customer service end is the same as select ing } else { printf("%s",buf); } } } } }
4, udp communication
1. Implementation method and its code
Select sock when creating socket_ For Dgram, udp protocol is selected. udp can be read and written at one time without stable link. Generally, recvfrom and sendto are directly used for reading and writing.
ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,struct sockaddr *src_addr, socklen_t *addrlen); sockfd: socket buf: buffer address len: Buffer size flags: 0 src_addr: (struct sockaddr *)&addr Outgoing. Peer address structure addrlen: Incoming and outgoing. Return value: the number of bytes of data successfully received. Failed:-1 errn. 0: The opposite end is closed. ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,const struct sockaddr *dest_addr, socklen_t addrlen); sockfd: socket buf: Buffer for storing data len: Data length flags: 0 src_addr: (struct sockaddr *)&addr Incoming. Target address structure addrlen: Address structure length. Return value: the number of data bytes successfully written out. fail -1, errno
server end #include <string.h> #include <stdio.h> #include <unistd.h> #include <arpa/inet.h> #include <ctype.h> #define SERV_PORT 8000 int main(void) { struct sockaddr_in serv_addr, clie_addr; socklen_t clie_addr_len; int sockfd; char buf[BUFSIZ]; char str[INET_ADDRSTRLEN]; int i, n; sockfd = socket(AF_INET, SOCK_DGRAM, 0); bzero(&serv_addr, sizeof(serv_addr)); serv_addr.sin_family = AF_INET; serv_addr.sin_addr.s_addr = htonl(INADDR_ANY); serv_addr.sin_port = htons(SERV_PORT); bind(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)); printf("Accepting connections ...\n"); while (1) { clie_addr_len = sizeof(clie_addr); n = recvfrom(sockfd, buf, BUFSIZ,0, (struct sockaddr *)&clie_addr, &clie_addr_len); if (n == -1) perror("recvfrom error"); printf("received from %s at PORT %d\n", inet_ntop(AF_INET, &clie_addr.sin_addr, str, sizeof(str)), ntohs(clie_addr.sin_port)); for (i = 0; i < n; i++) buf[i] = toupper(buf[i]); n = sendto(sockfd, buf, n, 0, (struct sockaddr *)&clie_addr, sizeof(clie_addr)); if (n == -1) perror("sendto error"); } close(sockfd); return 0; } client end #include <stdio.h> #include <string.h> #include <unistd.h> #include <arpa/inet.h> #include <ctype.h> #define SERV_PORT 8000 int main(int argc, char *argv[]) { struct sockaddr_in servaddr; int sockfd, n; char buf[BUFSIZ]; sockfd = socket(AF_INET, SOCK_DGRAM, 0); bzero(&servaddr, sizeof(servaddr)); servaddr.sin_family = AF_INET; inet_pton(AF_INET, "127.0.0.1", &servaddr.sin_addr); servaddr.sin_port = htons(SERV_PORT); bind(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr)); while (fgets(buf, BUFSIZ, stdin) != NULL) { n = sendto(sockfd, buf, strlen(buf), 0, (struct sockaddr *)&servaddr, sizeof(servaddr)); if (n == -1) perror("sendto error"); n = recvfrom(sockfd, buf, BUFSIZ, 0, NULL, 0); //NULL: don't care about information if (n == -1) perror("recvfrom error"); write(STDOUT_FILENO, buf, n); } close(sockfd); return 0; }
5, Local socket
Socket(AF_UNIX, SOCK_STREAM, 0) select AF_ UNIX, local communication is selected.
len = offsetof(struct sockaddr_un, sun_path) + strlen(servaddr.sun_path);
#include <stdio.h> #include <unistd.h> #include <sys/socket.h> #include <strings.h> #include <string.h> #include <ctype.h> #include <arpa/inet.h> #include <sys/un.h> #include <stddef.h> #include "wrap.h" #define SERV_ADDR "serv.socket" int main(void) { int lfd, cfd, len, size, i; struct sockaddr_un servaddr, cliaddr; char buf[4096]; lfd = Socket(AF_UNIX, SOCK_STREAM, 0); bzero(&servaddr, sizeof(servaddr)); servaddr.sun_family = AF_UNIX; strcpy(servaddr.sun_path, SERV_ADDR); len = offsetof(struct sockaddr_un, sun_path) + strlen(servaddr.sun_path); /* servaddr total len */ unlink(SERV_ADDR); /* Make sure that serv The sock file does not exist. bind will create it */ Bind(lfd, (struct sockaddr *)&servaddr, len); /* Parameter 3 cannot be sizeof(servaddr) */ Listen(lfd, 20); printf("Accept ...\n"); while (1) { len = sizeof(cliaddr); //AF_UNIX size + 108B cfd = Accept(lfd, (struct sockaddr *)&cliaddr, (socklen_t *)&len); len -= offsetof(struct sockaddr_un, sun_path); /* Get the length of the file name */ cliaddr.sun_path[len] = '\0'; /* Make sure there is no garbled code when printing */ printf("client bind filename %s\n", cliaddr.sun_path); while ((size = read(cfd, buf, sizeof(buf))) > 0) { for (i = 0; i < size; i++) buf[i] = toupper(buf[i]); write(cfd, buf, size); } close(cfd); } close(lfd); return 0; } #include <stdio.h> #include <string.h> #include <unistd.h> #include <arpa/inet.h> #include <ctype.h> #define SERV_PORT 8000 int main(int argc, char *argv[]) { struct sockaddr_in servaddr; int sockfd, n; char buf[BUFSIZ]; sockfd = socket(AF_INET, SOCK_DGRAM, 0); bzero(&servaddr, sizeof(servaddr)); servaddr.sin_family = AF_INET; inet_pton(AF_INET, "127.0.0.1", &servaddr.sin_addr); servaddr.sin_port = htons(SERV_PORT); bind(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr)); while (fgets(buf, BUFSIZ, stdin) != NULL) { n = sendto(sockfd, buf, strlen(buf), 0, (struct sockaddr *)&servaddr, sizeof(servaddr)); if (n == -1) perror("sendto error"); n = recvfrom(sockfd, buf, BUFSIZ, 0, NULL, 0); //NULL: do not care about peer information if (n == -1) perror("recvfrom error"); write(STDOUT_FILENO, buf, n); } close(sockfd); return 0; }