Socket programming practices (5) and socket programming practices
A short Connection client
// Transient client int main () {int loopCount = 20; char sendBuf [BUFSIZ] = {0}; char recvBuf [BUFSIZ] = {0 }; for (int I = 0; I <loopCount; ++ I) {sprintf (sendBuf, "Hello Server % d \ n", I ); // create a new socket int sockfd = socket (AF_INET, SOCK_STREAM, 0); if (sockfd =-1) {err_exit ("socket error ");} // fill in the server address and port number struct sockaddr_in serverAddr; serverAddr. sin_family = AF_INET; serverAddr. sin_port = htons (8002); // test the local machine. enter 127.0.0.1 (loopback address) serverAddr. sin_addr.s_addr = inet_addr ("127.0.0.1"); // connect to server if (connect (sockfd, (struct sockaddr *) & serverAddr, sizeof (serverAddr) =-1) {err_exit ("connect error");} // send data to the server if (write (sockfd, sendBuf, strlen (sendBuf) =-1) {err_exit ("write socket error");} int readCount = 0; // if (readCount = read (sockfd, recvBuf, sizeof (recvBuf) received from the server ))) <0) {err_exit ("read socket error");} // write it back to the terminal write (STDOUT_FILENO, recvBuf, strlen (recvBuf); close (sockfd );} return 0 ;}
Note: The server is based on the Code in the previous blog.
Design and Implementation of point-to-point chat programs
Features of point-to-point chat programs:
Code implementation and description
// Complete serever code and description # include "commen. h "int main () {// install the signal receiving function signal (SIGUSR1, onSignal); // create the listening socket int sockfd = socket (AF_INET, SOCK_STREAM, 0 ); if (sockfd =-1) {err_exit ("socket error");} // Add address multiplexing int optval = 1; if (setsockopt (sockfd, SOL_SOCKET, SO_REUSEADDR, & optval, sizeof (optval) =-1) {err_exit ("setsockopt SO_REUSEADDR error");} // bind the listening socket to the local struct sockaddr_in serverAddr; serverAddr. sin_family = AF_INET; // you can delete serverAddr from this row. sin_port = htons (8001); serverAddr. sin_addr.s_addr = INADDR_ANY; // bind any IP address of the Local Machine if (bind (sockfd, (struct sockaddr *) & serverAddr, sizeof (serverAddr) =-1) {err_exit ("bind error");} // enable listening socket // once listen is called, sockfd programming passive socket-> wait for client connection (only connections can be accepted, cannot send connection) if (listen (sockfd, SOMAXCONN) =-1) {err_exit ("listen error");} // if there is no client connection, the system call will always block struct sockaddr_in peerAddr; socklen_t peerLen = sizeof (peerAddr); int peerSockfd = accept (sockfd, (struct sockaddr *) & peerAddr, & peerLen ); if (peerSockfd =-1) {err_exit ("accept error");} // the Client comes to cout <"Client Connected:" <endl; cout <"\ tpeerAddr. sin_addr: "<inet_ntoa (peerAddr. sin_addr) <endl; cout <"\ tpeerAddr. sin_port: "<ntohs (peerAddr. sin_port) <endl; // create a sub-process pid_t pid = fork (); if (pid =-1) {err_exit ("fork error ");} // parent process: receives data from the client-> prints data to the screen if (pid> 0) {close (STDIN_FILENO ); // disable useless file descriptor char recvBuf [BUFSIZ] = {0}; int readCount = 0; // receives data from the client while (readCount = read (peerSockfd, recvBuf, sizeof (recvBuf)> 0) {recvBuf [readCount] = 0; // print it to the screen fprintf (stdout, "% s", recvBuf); memset (recvBuf, 0, sizeof (recvBuf);} // The peer has closed if (readCount = 0) {close (peerSockfd ); // disable the Communication Node cout <"peer connect closed" <endl; // send the SIGUSR1 signal to the sub-process and kill the sub-process (pid, SIGUSR1 ); _ exit (0);} // receives the error else if (readCount =-1) {close (peerSockfd); // sends the SIGUSR1 signal to the sub-process, kill the sub-process (pid, SIGUSR1); err_exit ("read error") ;}} else if (pid = 0) // sub-process: receiving data from the keyboard-> writing data to the client {close (STDOUT_FILENO); char sendBuf [BUFSIZ] = {0}; // receiving data from the keyboard while (true) {if (fgets (sendBuf, sizeof (sendBuf), stdin) = NULL) {break;} else if (strncmp (sendBuf, "quit", 4) = 0) {close (peerSockfd); kill (getppid (), SIGUSR2); break;} // send it to the client if (write (peerSockfd, sendBuf, strlen (sendBuf )) = ssize_t (-1) {close (peerSockfd); err_exit ("write socket error");} memset (sendBuf, 0, sizeof (sendBuf ));}} close (sockfd); return 0 ;}
// Complete client code and description # include "commen. h "int main () {signal (SIGUSR1, onSignal); // create a new socket int sockfd = socket (AF_INET, SOCK_STREAM, 0); if (sockfd =-1) {err_exit ("socket error");} // enter the server IP address and port number struct sockaddr_in serverAddr; serverAddr. sin_family = AF_INET; serverAddr. sin_port = htons (8001); serverAddr. sin_addr.s_addr = inet_addr ("127.0.0.1"); // connect to server if (connect (sockfd, (struct sockaddr *) & serverAddr, sizeof (serverAddr) =-1) {err_exit ("connect error");} pid_t pid = fork (); if (pid =-1) {err_exit ("fork error");} // parent process: receive data from the keyboard-> send it to the server if (pid> 0) {close (STDOUT_FILENO); char sendBuf [BUFSIZ] = {0 }; // receives data from the keyboard while (true) {if (fgets (sendBuf, sizeof (sendBuf), stdin) = NULL) {break;} else if (strncmp (sendBuf, "quit", 4) = 0) {close (sockfd); // send the SIGUSR1 signal to the sub-process and disable kill (pid, SIGUSR1 ); _ exit (0);} // send to the server if (write (sockfd, sendBuf, strlen (sendBuf) = ssize_t (-1) {close (sockfd ); err_exit ("write socket error");} memset (sendBuf, 0, sizeof (sendBuf);} else if (pid = 0) // sub-process: receive data from the server and print it to the screen {close (STDIN_FILENO); char recvBuf [BUFSIZ] = {0}; int readCount = 0; // receives data from the server while (readCount = read (sockfd, recvBuf, sizeof (recvBuf)> 0) {recvBuf [readCount] = 0; // print it to the screen fprintf (stdout, "% s", recvBuf); memset (recvBuf, 0, sizeof (recvBuf);} if (readCount = 0) {close (sockfd); cout <"peer connect closed" <endl; // send the SIGUSR2 signal to the parent process and disable kill (getppid (), SIGUSR2 ); _ exit (0);} else if (readCount =-1) {close (sockfd); err_exit ("read error") ;}} return 0 ;}
We can see that there is no port occupation or zombie process at this time!
Appendix-commen. h
#ifndef COMMEN_H_INCLUDED#define COMMEN_H_INCLUDED#include <unistd.h>#include <signal.h>#include <errno.h>#include <fcntl.h>#include <sys/types.h>#include <sys/wait.h>#include <sys/stat.h>#include <sys/ipc.h>#include <sys/shm.h>#include <sys/msg.h>#include <sys/sem.h>#include <sys/socket.h>#include <arpa/inet.h>#include <sys/socket.h>#include <netinet/in.h>#include <arpa/inet.h>#include <string.h>#include <stdio.h>#include <stdlib.h>#include <iostream>using namespace std;void err_exit(std::string str){ perror(str.c_str()); exit(EXIT_FAILURE);}struct SendStruct{ int type; char text[BUFSIZ];};void onSignal(int signalNumber){ switch (signalNumber) { case SIGUSR1: cout << "child receive SIGUSR1" << signalNumber << endl; _exit(0); case SIGUSR2: cout << "parent receive SIGUSR2: " << signalNumber << endl; _exit(0); default: cout << "RECV OTHRER SIGNAL" << endl; }}#endif // COMMEN_H_INCLUDED
Appendix-Makefile
CC = g++ CPPFLAGS = -Wall -g -pthreadBIN = server clientSOURCES = $(BIN.=.cpp).PHONY: clean all all: $(BIN)$(BIN): $(SOURCES)clean: -rm -rf $(BIN) bin/ obj/ core