Review:
UC growth path 1
UC growth path 2
UC growth path 3
UC growth path 4
UC growth path 5
UC growth path 6
UC growth path 7
UC growth path 8
UC growth path 9
UC growth path 10
UC growth path 11
UC growth path 12
1, Network programming model and Implementation Based on TCP
-
There are two types of transport layer: TCP and UDP
-
TCP is connection oriented, reliable and secure, but inefficient
-
UDP is packet oriented, unreliable, but efficient
-
Establish TCP connection and disconnect: the process of establishing a connection is called the famous three handshakes and four waves when disconnected
-
Server programming model
//1. Create a socket endpoint and return a file descriptor. lfd socket(2) //2. Bind the lfd to the ip address and port number of the server bind(2) //3. Set lfd to passive connection mode to monitor the arrival of client connection. The arrival of a client connection is put into the pending connection queue listen(2) //4. Take a client connection from the undecided connection queue and return the file descriptor of the client connection. Use this file descriptor to communicate with the client. There is no data in the pending connection queue, blocking waiting for the client's connection to arrive accept(2) while(1){ //5 get data from client read() //6. Process the acquired data //7. Send the processing result back to the client write() //8. Close this connection close() }
- Programming model of client
//1. Create a communication endpoint and return a file descriptor socket(2) //2. Use this file descriptor to initiate a connection to the server connect(2) //3. Send message to server write() //4. Wait for the corresponding message from the server read() //5. Process the corresponding messages of the server //6. Close the connection with the server and overnight communication close()
- socket(2)
#include <sys/types.h> /* See NOTES */ #include <sys/socket.h> int socket(int domain, int type, int protocol); //Function: create a communication endpoint and return a file descriptor //parameter //domain: //1)AF_INET IPv4 Internet protocols ip(7) //2)AF_INET6 IPv6 Internet protocols ipv6(7) //... //type //1)SOCK_STREAM:TCP //2)SOCK_DGRAM:UDP //... //protocol:0 //Return value: successfully return a file descriptor for the new socket; The error returns - 1, and errno is set
- bind(2)
#include <sys/types.h> /* See NOTES */ #include <sys/socket.h> int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen); //Function: bind a name to the socket //Parameters: //sockfd: Specifies the specific socket (like the SIM card slot of the mobile phone) //addr: Specifies the address and port number of the server (like SIM card) //addrlen: Specifies the effective space size of addr //Return value: 0 is returned successfully; The error returns - 1, and error is set struct sockaddr { sa_family_t sa_family; char sa_data[14]; };
- listenl(2)
#include <sys/types.h> /* See NOTES */ #include <sys/socket.h> int listen(int sockfd, int backlog); //Function: establish a connection on the specified socket //Parameters: //Sockfd: return value of socket (2) //backlog: Specifies the maximum length of the pending connection queue //Return value: 0 is returned successfully; The error returns - 1, and error is set
- accept(2)
#include <sys/types.h> /* See NOTES */ #include <sys/socket.h> int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen); //Function: receive connections on the specified socket //Parameters: //sockfd: socket(2) is specified. Return value of socket(2) //Addr: if addr is NULL, addrlen should also be set to NULL; //The address space specified by addr is filled with the contents of the address family of the client //addrlen: value - result parameter, which specifies the effective space size of addr //Return value: error returns - 1, errno is set; A nonnegative integer and a file descriptor are returned successfully, //And the connection descriptor of the client, and use this connection descriptor to communicate with the client.
- connect(2)
#include <sys/types.h> /* See NOTES */ #include <sys/socket.h> int connect(int sockfd, const struct sockaddr *addr,socklen_t addrlen); //Function: initiate a connection on a socket and connect the socket to the address pointed to by addr //Parameters: //sockfd: socket specified //addr: address specified //addrlen: Specifies the size of addr space //Return value: 0 is returned successfully; The error returns - 1, and errno is set
- IPV4 family, IPV6 family
- Universal family struct sockaddr
struct sockaddr { sa_family_t sa_family; char sa_data[14]; };
- IPV4 family address, which can be viewed using man 7 ip
struct sockaddr_in { sa_family_t sin_family; /* address family: AF_INET */ in_port_t sin_port; /* port in network byte order */ struct in_addr sin_addr; /* internet address */ }; /* Internet address. */ struct in_addr { uint32_t s_addr; /* address in network byte order */ };
- Configure port number and ip address
- Conversion between network byte order and host byte order, htonl(3)
uint32_t htonl(uint32_t hostlong); uint16_t htons(uint16_t hostshort); uint32_t ntohl(uint32_t netlong); uint16_t ntohs(uint16_t netshort); //h:host //n:net //s:short //l:long //to
- ip address conversion: string and unsigned long integer conversion, inet_pton(3), inet_ntop(3)
#include <arpa/inet.h> int inet_pton(int af, const char *src, void *dst); //Function: Text -- > binary //Parameters: //af:AF_INET or AF_INET6 //src: ip in string format, to be converted //dst: store the converted results //Return value: 1 if successful; If af is invalid, return - 1 and errno is set; src invalid return 0 #include <arpa/inet.h> const char *inet_ntop(int af, const void *src, char *dst, socklen_t size); //Function: binary - > text //Parameters: //af:AF_INET or AF_INET6 //src:ip address (binary) //dst: the converted ip address (text) is stored in the space specified by this address //size: Specifies the number of bytes available for dst buffer //Return value: error returns NULL, and errno is set; The address pointed to by dst is returned successfully, and the converted result is stored in this space
eg: write server-side and client-side programs based on TCP
- The server side is responsible for converting the string sent by the client to uppercase, server c
- The client is responsible for sending the string to the server, and then outputting the string converted by the server to the display, client c
- server.c
#include <stdio.h> #include <sys/types.h> #include <sys/socket.h> #include <ctype.h> #include <unistd.h> #include <netinet/in.h> #include <arpa/inet.h> int main(void) { struct sockaddr_in serv; int cfd;//connect fd char buf[128]; //Create a socket and return the file descriptor ldf of the socket int lfd = socket(AF_INET, SOCK_STREAM, 0); if(lfd==-1){ perror("socket"); return -1; } //Initialize members of serv serv.sin_family=AF_INET; serv.sin_port=htons(1024); //INADDR_ANY stands for all ip addresses of this machine serv.sin_addr.s_addr=htonl(INADDR_ANY); //Bind the lfd to the local ip address and port int b = bind(lfd, (struct sockaddr *)&serv, sizeof(serv)); if(b==-1){ perror("bind"); return -1; } //Set lfd to passive link mode to monitor the arrival of client connection. If a client's connection arrives, put the connection into the pending connection queue listen(lfd, 5); while(1){ //Take the first connection from the undecided connection queue for processing. If there is no pending connection, block and wait. If there is, return a file descriptor cfd = accept(lfd, NULL, NULL); if(cfd==-1){ perror("accept"); return -1; } //At this time, the three handshakes have been completed and the data processing is complete //Read client requests int r = read(cfd, buf, 128); int i; //Processing client requests for(i=0; i<r; i++){ buf[i]=toupper(buf[i]);//Convert characters to uppercase } //Respond to the client and respond the processing information to the client write(cfd, buf, r); //Close the connection with the client and end the connection close(cfd); } return 0; }
- client.c
#include <stdio.h> #include <sys/types.h> #include <sys/socket.h> #include <string.h> #include <unistd.h> #include <netinet/in.h> #include <arpa/inet.h> int main(void) { struct sockaddr_in serv;//ip address and port number of the server char *msg = "this is a test...\n"; char buf[128]; //Create a socket and return the file description of the socket int lfd = socket(AF_INET, SOCK_STREAM, 0); if(lfd==-1){ perror("socket"); return -1; } //Initialize the ip address and port number of the server serv.sin_family=AF_INET;//IPV4 serv.sin_port=htons(1024); //ip address of the server, 127.0.0.1, text -- > binary inet_pton(AF_INET, "127.0.0.1", &serv.sin_addr); //Use lfd to initiate a connection to the server. If this function is executed successfully, three handshakes are successful int conn=connect(lfd, (struct sockaddr*)&serv, sizeof(serv)); if(conn){ perror("connect"); return -1; } //Send string to server write(lfd, msg, strlen(msg)); //Wait for the response information of the server. If there is no response, block the waiting int r=read(lfd, buf, 128); //Output the acquired response information to the display write(1, buf, r); //Close the connection with the server and end communication close(lfd); return 0; }
- Improve eg
server.c
#include <stdio.h> #include <sys/types.h> /* See NOTES */ #include <sys/socket.h> #include <ctype.h> #include <unistd.h> #include <netinet/in.h> #include <arpa/inet.h> int main(void) { struct sockaddr_in serv, clie; int cfd;//connect fd char buf[128]; //Create a socket and return the file descriptor ldf of the socket int lfd = socket(AF_INET, SOCK_STREAM, 0); if(lfd==-1){ perror("socket"); return -1; } //Initialize members of serv serv.sin_family=AF_INET; serv.sin_port=htons(1024); //INADDR_ANY stands for all ip addresses of this machine serv.sin_addr.s_addr=htonl(INADDR_ANY); //Bind the lfd to the local ip address and port int b = bind(lfd, (struct sockaddr *)&serv, sizeof(serv)); if(b==-1){ perror("bind"); return -1; } //Set lfd to passive link mode to monitor the arrival of client connection. If a client's connection arrives, put the connection into the pending connection queue listen(lfd, 5); while(1){ socklen_t cli_len = sizeof(clie); //Take the first connection from the undecided connection queue for processing. If there is no pending connection, block and wait. If there is, return a file descriptor cfd = accept(lfd, (struct sockaddr *)&clie, &cli_len); if(cfd==-1){ perror("accept"); return -1; } char IP[64]; //binary-->text printf("%s\n", inet_ntop(AF_INET, &clie.sin_addr, IP, 64)); //At this time, the three handshakes have been completed and the data processing is complete //Read client requests int r = read(cfd, buf, 128); int i; //Processing client requests for(i=0; i<r; i++){ buf[i]=toupper(buf[i]);//Convert characters to uppercase } //Respond to the client and respond the processing information to the client write(cfd, buf, r); //Close the connection with the client and end the connection close(cfd); } return 0; }
client.c
perror("connect"); return -1; } //Send string to server write(lfd, msg, strlen(msg)); //Wait for the response information of the server. If there is no response, block the waiting int r=read(lfd, buf, 128); //Output the acquired response information to the display write(1, buf, r); //Close the connection with the server and end communication close(lfd); return 0; }
- Package eg
t_net.h
#ifndef T_NET_H_ #define T_NET_H_ /*include file*/ #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> /*Declaration of type*/ typedef struct sockaddr_in SA4; typedef struct sockaddr SA; /*Function, create a socket, and bind the returned descriptor to the local address*/ int socket_b(int port); int trans(int fd);//Business processing of client #endif
t_net.c
#include <stdio.h> #include "t_net.h" int socket_b(int port) { SA4 serv; //Create a socket and return the file descriptor ldf of the socket int lfd = socket(AF_INET, SOCK_STREAM, 0); if(lfd==-1){ perror("socket"); return -1; } //Initialize members of serv serv.sin_family=AF_INET; serv.sin_port=htons(port); //INADDR_ANY represents all ip addresses of the machine serv.sin_addr.s_addr=htonl(INADDR_ANY); //Bind the lfd to the local ip address and port int b = bind(lfd, (SA *)&serv, sizeof(serv)); if(b==-1){ perror("bind"); return -1; } return lfd; } //Business processing int trans(int fd) { char buf[128]; //Read client requests int r=read(fd,buf,128); int i; //Processing client requests for(i=0;i<r;i++){ buf[i]=toupper(buf[i]);//Convert characters to uppercase } write(fd, buf, r); return 0; }
serverp.c
#include <stdio.h> #include <unistd.h> #include "t_net.h" int main(void) { SA4 clie; int cfd;//connect fd int lfd=socket_b(1024); if(lfd==-1) return -1; //Set lfd to passive link mode to monitor the arrival of client connection. If a client's connection arrives, put the connection into the pending connection queue listen(lfd, 5); while(1){ socklen_t cli_len = sizeof(clie); //Take the first connection from the undecided connection queue for processing. If there is no pending connection, block and wait. If there is, return a file descriptor cfd = accept(lfd, (SA *)&clie, &cli_len); if(cfd==-1){ perror("accept"); return -1; } char IP[64]; //binary-->text printf("%s\n", inet_ntop(AF_INET, &clie.sin_addr, IP, 64)); //At this time, the three handshakes have been completed and the data processing is complete trans(cfd);//Business processing //Close the connection with the client and end the connection close(cfd); } return 0; }
client.c
inet_pton(AF_INET, argv[1], &serv.sin_addr); //Use lfd to initiate a connection to the server. If this function is executed successfully, three handshakes are successful int conn=connect(lfd, (SA *)&serv, sizeof(serv)); if(conn==-1){ perror("connect"); return -1; } //Send string to server write(lfd, msg, strlen(msg)); //Wait for the response information of the server. If there is no response, block the waiting int r=read(lfd, buf, 128); //Output the acquired response information to the display write(1, buf, r); //Close the connection with the server and end communication close(lfd); return 0; }
- eg: the client and server connect at one time and transmit multiple strings. If the client wants to end the connection, enter exit.
t_net.h
#ifndef T_NET_H_ #define T_NET_H_ /*include file*/ #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> /*Declaration of type*/ typedef struct sockaddr_in SA4; typedef struct sockaddr SA; /*Function, create a socket, and bind the returned descriptor to the local address*/ int socket_b(int port); int trans(int fd);//Business processing of client #endif
t_net.c
#include <stdio.h> #include <string.h> #include "t_net.h" int socket_b(int port) { SA4 serv; //Create a socket and return the file descriptor ldf of the socket int lfd = socket(AF_INET, SOCK_STREAM, 0); if(lfd==-1){ perror("socket"); return -1; } //Initialize members of serv serv.sin_family=AF_INET; serv.sin_port=htons(port); //INADDR_ANY stands for all ip addresses of this machine serv.sin_addr.s_addr=htonl(INADDR_ANY); //Bind the lfd to the local ip address and port int b = bind(lfd, (SA *)&serv, sizeof(serv)); if(b==-1){ perror("bind"); return -1; } return lfd; } //Business processing int trans(int fd) { char buf[128]; while(1){ memset(buf, 0, 128); //Read client requests int r=read(fd,buf,128); int i; //Processing client requests for(i=0;i<r;i++){ buf[i]=toupper(buf[i]);//Convert characters to uppercase } write(fd, buf, r); if(strcmp(buf,"EXIT")==0) break; } return 0; }
serverp.c
#include <stdio.h> #include <unistd.h> #include "t_net.h" int main(void) { SA4 clie; int cfd;//connect fd int lfd=socket_b(1024); if(lfd==-1) return -1; //Set lfd to passive link mode to monitor the arrival of client connection. If a client's connection arrives, put the connection into the pending connection queue listen(lfd, 5); while(1){ socklen_t cli_len = sizeof(clie); //Take the first connection from the undecided connection queue for processing. If there is no pending connection, block and wait. If there is, return a file descriptor cfd = accept(lfd, (SA *)&clie, &cli_len); if(cfd==-1){ perror("accept"); return -1; } char IP[64]; //binary-->text printf("%s\n", inet_ntop(AF_INET, &clie.sin_addr, IP, 64)); //At this time, the three handshakes have been completed and the data processing is complete trans(cfd);//Business processing //Close the connection with the client and end the connection close(cfd); } return 0; }
clientp.c
#include <stdio.h> #include <string.h> #include <unistd.h> #include "t_net.h" int main(int argc, char* argv[]) { SA4 serv;//ip address and port number of the server char buf[128]; char msg[128]; //Create a socket and return the file description of the socket int lfd = socket(AF_INET, SOCK_STREAM, 0); if(lfd==-1){ perror("socket"); return -1; } //Initialize the ip address and port number of the server serv.sin_family=AF_INET;//IPV4 serv.sin_port=htons(1024); //ip address of the server, 127.0.0.1, text -- > binary inet_pton(AF_INET, argv[1], &serv.sin_addr); //Use lfd to initiate a connection to the server. If this function is executed successfully, three handshakes are successful int conn=connect(lfd, (SA *)&serv, sizeof(serv)); if(conn==-1){ perror("connect"); return -1; } while(gets(msg)){ //Send string to server write(lfd, msg, strlen(msg)); memset(buf, 0, 128); //Wait for the response information of the server. If there is no response, block the waiting int r=read(lfd, buf, 128); if(strcmp(buf,"EXIT")==0) break; //Output the acquired response information to the display write(1, buf, r); printf("\n"); } //Close the connection with the server and end communication close(lfd); return 0; }
2, Implementation of concurrent server
- Implementation of Concurrency: multiplexing, threads, processes
- Parent process
- Take a connection from the undecided connection queue
- Create child process
- Close the connection descriptor of the client
- Reclaim the resources of the child process, waitpid()
- Subprocess
- close(lfd)
- Handle the specific business of the client
- close(cfd)
- exit(0)
eg: Code of concurrent server
t_net.h
#ifndef T_NET_H_ #define T_NET_H_ /*include file*/ #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> /*Declaration of type*/ typedef struct sockaddr_in SA4; typedef struct sockaddr SA; /*Function, create a socket, and bind the returned descriptor to the local address*/ int socket_b(int port); int trans(int fd);//Business processing of client #endif
t_net.c
#include <stdio.h> #include <string.h> #include "t_net.h" int socket_b(int port) { SA4 serv; //Create a socket and return the file descriptor ldf of the socket int lfd = socket(AF_INET, SOCK_STREAM, 0); if(lfd==-1){ perror("socket"); return -1; } //Initialize members of serv serv.sin_family=AF_INET; serv.sin_port=htons(port); //INADDR_ANY stands for all ip addresses of this machine serv.sin_addr.s_addr=htonl(INADDR_ANY); //Bind the lfd to the local ip address and port int b = bind(lfd, (SA *)&serv, sizeof(serv)); if(b==-1){ perror("bind"); return -1; } return lfd; } //Business processing int trans(int fd) { char buf[128]; while(1){ memset(buf, 0, 128); //Read client requests int r=read(fd,buf,128); int i; //Processing client requests for(i=0;i<r;i++){ buf[i]=toupper(buf[i]);//Convert characters to uppercase } write(fd, buf, r); if(strcmp(buf,"EXIT")==0) break; } return 0; }
servers.c
#include <stdio.h> #include <unistd.h> #include "t_net.h" #include <stdlib.h> #include <sys/wait.h> int main(void) { SA4 clie; int cfd;//connect fd int lfd=socket_b(1024); if(lfd==-1) return -1; //Set lfd to passive link mode to monitor the arrival of client connection. If a client's connection arrives, put the connection into the pending connection queue listen(lfd, 5); while(1){ socklen_t cli_len = sizeof(clie); //Take the first connection from the undecided connection queue for processing. If there is no pending connection, block and wait. If there is, return a file descriptor cfd = accept(lfd, (SA *)&clie, &cli_len); if(cfd==-1){ perror("accept"); return -1; } char IP[64]; //binary-->text printf("%s\n", inet_ntop(AF_INET, &clie.sin_addr, IP, 64)); //Create child process pid_t pid=fork(); if(pid==-1){ perror("fork"); return -1; } if(pid==0){//Tasks of child processes close(lfd); //At this time, the three handshakes have been completed and the data processing is complete trans(cfd);//Business processing //Close the connection with the client and end the connection close(cfd); exit(0); } else{//Tasks of the parent process close(cfd); //Non blocking waitpid(-1, NULL, WNOHANG); } } return 0; }
clientp.c
#include <stdio.h> #include <string.h> #include <unistd.h> #include "t_net.h" int main(int argc, char* argv[]) { SA4 serv;//ip address and port number of the server char buf[128]; char msg[128]; //Create a socket and return the file description of the socket int lfd = socket(AF_INET, SOCK_STREAM, 0); if(lfd==-1){ perror("socket"); return -1; } //Initialize the ip address and port number of the server serv.sin_family=AF_INET;//IPV4 serv.sin_port=htons(1024); //ip address of the server, 127.0.0.1, text -- > binary inet_pton(AF_INET, argv[1], &serv.sin_addr); //Use lfd to initiate a connection to the server. If this function is executed successfully, three handshakes are successful int conn=connect(lfd, (SA *)&serv, sizeof(serv)); if(conn==-1){ perror("connect"); return -1; } while(gets(msg)){ //Send string to server write(lfd, msg, strlen(msg)); memset(buf, 0, 128); //Wait for the response information of the server. If there is no response, block the waiting int r=read(lfd, buf, 128); if(strcmp(buf,"EXIT")==0) break; //Output the acquired response information to the display write(1, buf, r); printf("\n"); } //Close the connection with the server and end communication close(lfd); return 0; }
Supplement: setsockopt(2) solve the problem of ip address reuse (address reuse is because it needs to be implemented in the kernel state below the transport layer. The address resources just used have not been recycled, and the address reuse problem will occur if the address is reused immediately)
#include <sys/types.h> /* See NOTES */ #include <sys/socket.h> int getsockopt(int sockfd, int level, int optname, void *optval, socklen_t *optlen); int setsockopt(int sockfd, int level, int optname, const void *optval, socklen_t optlen);
3, UDP based programming model and its implementation
- Using UDP for network communication, there is no need to establish a connection at all
- Model
//Server: //1. Create a socket communication endpoint //2. Bind the socket to the local address while(1){ //3. Use recvfrom blocking to wait for the arrival of client data //4. Process the data obtained from the client //5. Respond the result to the client } //client: //1. Create a socket //2. Use this socket to send messages to the server //3. Block the response message waiting for the server //4. Process response message //5. Close the socket and end the process of the client
- sendto(2) \ recvfrom(2)
#include <sys/types.h> #include <sys/socket.h> ssize_t sendto(int sockfd, const void *buf, size_t len, int flags, const struct sockaddr *dest_addr, socklen_t addrlen); //Function: Send a message on socket //parameter //sockfd: Specifies the socket on which to send messages //buf: Specifies the address where the data to be sent is stored //len: length of data to be sent //flags:0 (see man help for others) //dest_addr: the destination address is specified //addrlen: dest specified_ Address space size pointed to by addr //Return value: successfully returns the number of bytes sent; The error returns - 1, and errno is set #include <sys/types.h> #include <sys/socket.h> ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr *src_addr, socklen_t *addrlen); //Function: receive a message from socket //parameter //sockfd: Specifies the socket on which to receive messages //buf: Specifies the address. Use this address to start storing messages //len: Specifies the size of the buf space //flags:0 (see man help for others) //src_addr: fill the content of the client's address family in the specified address space //addrlen: value - result parameter, which specifies the effective space size of addr //Return value: successfully returns the number of bytes received; Error returned - 1
eg: programming the server and client of UDP communication
userver.c
#include <stdio.h> #include "t_net.h" #include <ctype.h> int main(void) { SA4 serv, clie; char buf[128]; socklen_t cli_len; //Create udp based socket int fd=socket(AF_INET, SOCK_DGRAM, 0); if(fd==-1){ perror("socket"); return -1; } //Initialize the ip address and port number of the server serv.sin_family=AF_INET; serv.sin_port=htons(4000); serv.sin_addr.s_addr=htonl(INADDR_ANY); //Bind fd to the local ip address and port number int b=bind(fd, (SA *)&serv, sizeof(serv)); if(b==-1){ perror("bind"); return -1; } while(1){ cli_len=sizeof(SA4); //Get data from client int rcv=recvfrom(fd, buf, 128, 0, (SA *)&clie, &cli_len); if(rcv==-1){ perror("recvfrom"); return -1; } int i; for(i=0; i<rcv; i++){ buf[i]=toupper(buf[i]); } //Send the processing result to the client int s=sendto(fd, buf, rcv, 0, (SA *)&clie, sizeof(SA4)); if(s==-1){ perror("sendto"); return -1; } } return 0; }
uclient.c
#include <stdio.h> #include "t_net.h" #include <string.h> #include <unistd.h> int main(int argc, char* argv[]) { char *msg="this is a test...\n"; SA4 serv; char buf[128]; //Create a socket based on udp int fd=socket(AF_INET, SOCK_DGRAM, 0); if(fd==-1){ perror("socket"); return -1; } //Initialize the ip address and port number of the server serv.sin_family=AF_INET; serv.sin_port=htons(4000); inet_pton(AF_INET, argv[1], &serv.sin_addr); //Send message to server int s=sendto(fd,msg,strlen(msg),0,(SA *)&serv,sizeof(SA4)); if(s==-1){ perror("sendto"); return -1; } //Blocking waiting for response messages from the server int rcv=recvfrom(fd,buf,128,0,NULL,NULL); if(rcv==-1){ perror("recvfrom"); return -1; } //Output the response message of the server to the display write(1, buf, rcv); return 0; }