linux c socket之多进程任务

/* * File: TCPEchoServer-Fork.c * Author: 云守护 */#include <stdio.h>#include <stdlib.h>#include <string.h>#include <unistd.h>#include <sys/wait.h>#include "Utility.h"int main(int argc, char** argv) {if (argc != 2)DieWithUserMessage("param", "<server port/Service>");char *service = argv[1];int server_sock = SetupTCPServerSocket(service);if (server_sock < 0)DieWithUserMessage("SetupTCPServerSocket() failed!", "unable to establish");unsigned int childProcCount = 0;for (;;) {int client_sock = AcceptTCPConnection(server_sock);pid_t pid = fork(); //新进程if (pid < 0)DieWithSystemMessage("fork() failed!");else if (pid == 0) {//子进程close(server_sock);HandleTCPClient(client_sock);exit(0);}//父进程printf("with child process:%d\n", pid);close(client_sock);childProcCount++; //子进程加一while (childProcCount)//清除所有僵尸进程{pid = waitpid((pid_t) – 1, NULL, WNOHANG); //非阻塞等待if (pid < 0)DieWithSystemMessage("waitpid() failed!");else if (pid == 0)break;elsechildProcCount–;}}return (EXIT_SUCCESS);}/* * File: Utility.h * Author: 云守护 542335495@qq.com */#ifndef UTILITY_H#defineUTILITY_H#ifdef__cplusplusextern "C" {#endif#include <stdbool.h>#include <stdio.h>#include <sys/socket.h>// Handle error with user msgvoid DieWithUserMessage(const char *msg, const char *detail);// Handle error with sys msgvoid DieWithSystemMessage(const char *msg);// Print socket addressvoid PrintSocketAddress(const struct sockaddr *address, FILE *stream);// Test socket address equalitybool SockAddrsEqual(const struct sockaddr *addr1, const struct sockaddr *addr2);// Create, bind, and listen a new TCP server socketint SetupTCPServerSocket(const char *service);// Accept a new TCP connection on a server socketint AcceptTCPConnection(int servSock);// Handle new TCP clientvoid HandleTCPClient(int clntSocket);// Create and connect a new TCP client socketint SetupTCPClientSocket(const char *server, const char *service);enum sizeConstants { MAXSTRINGLENGTH = 128, BUFSIZE = 512,};#ifdef__cplusplus}#endif#endif/* UTILITY_H *//* * File: Utility.c * Author: 云守护 */#include <stdio.h>#include <stdlib.h>#include <string.h>#include <stdbool.h>#include <arpa/inet.h>#include <unistd.h>#include <sys/types.h>#include <sys/socket.h>#include <netdb.h>#include "Utility.h"static const int MAXPENDING = 5; // Maximum outstanding connection requestsvoid DieWithUserMessage(const char *msg, const char *detail) { fputs(msg, stderr); fputs(": ", stderr); fputs(detail, stderr); fputc(‘\n’, stderr); exit(1);}void DieWithSystemMessage(const char *msg) { perror(msg); exit(1);}void PrintSocketAddress(const struct sockaddr *address, FILE *stream) { // Test for address and stream if (address == NULL || stream == NULL)return; void *numericAddress; // Pointer to binary address // Buffer to contain result (IPv6 sufficient to hold IPv4) char addrBuffer[INET6_ADDRSTRLEN]; in_port_t port; // Port to print // Set pointer to address based on address family switch (address->sa_family) { case AF_INET:numericAddress = &((struct sockaddr_in *) address)->sin_addr;port = ntohs(((struct sockaddr_in *) address)->sin_port);break; case AF_INET6:numericAddress = &((struct sockaddr_in6 *) address)->sin6_addr;port = ntohs(((struct sockaddr_in6 *) address)->sin6_port);break; default:fputs("[unknown type]", stream); // Unhandled typereturn; } // Convert binary to printable address if (inet_ntop(address->sa_family, numericAddress, addrBuffer,sizeof(addrBuffer)) == NULL)fputs("[invalid address]", stream); // Unable to convert else {fprintf(stream, "%s", addrBuffer);if (port != 0)// Zero not valid in any socket addrfprintf(stream, "-%u", port); }}bool SockAddrsEqual(const struct sockaddr *addr1, const struct sockaddr *addr2) { if (addr1 == NULL || addr2 == NULL)return addr1 == addr2; else if (addr1->sa_family != addr2->sa_family)return false; else if (addr1->sa_family == AF_INET) {struct sockaddr_in *ipv4Addr1 = (struct sockaddr_in *) addr1;struct sockaddr_in *ipv4Addr2 = (struct sockaddr_in *) addr2;return ipv4Addr1->sin_addr.s_addr == ipv4Addr2->sin_addr.s_addr&& ipv4Addr1->sin_port == ipv4Addr2->sin_port; } else if (addr1->sa_family == AF_INET6) {struct sockaddr_in6 *ipv6Addr1 = (struct sockaddr_in6 *) addr1;struct sockaddr_in6 *ipv6Addr2 = (struct sockaddr_in6 *) addr2;return memcmp(&ipv6Addr1->sin6_addr, &ipv6Addr2->sin6_addr,sizeof(struct in6_addr)) == 0 && ipv6Addr1->sin6_port== ipv6Addr2->sin6_port; } elsereturn false;}int SetupTCPClientSocket(const char *host, const char *service) { // Tell the system what kind(s) of address info we want struct addrinfo addrCriteria;// Criteria for address match memset(&addrCriteria, 0, sizeof(addrCriteria)); // Zero out structure addrCriteria.ai_family = AF_UNSPEC;// v4 or v6 is OK addrCriteria.ai_socktype = SOCK_STREAM;// Only streaming sockets addrCriteria.ai_protocol = IPPROTO_TCP;// Only TCP protocol // Get address(es) struct addrinfo *servAddr; // Holder for returned list of server addrs int rtnVal = getaddrinfo(host, service, &addrCriteria, &servAddr); if (rtnVal != 0)DieWithUserMessage("getaddrinfo() failed", gai_strerror(rtnVal)); int sock = -1; struct addrinfo *addr = servAddr; while ( addr != NULL) {// Create a reliable, stream socket using TCPsock = socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol);if (sock < 0)continue; // Socket creation failed; try next address// Establish the connection to the echo serverif (connect(sock, addr->ai_addr, addr->ai_addrlen) == 0)break;// Socket connection succeeded; break and return socketclose(sock); // Socket connection failed; try next addresssock = -1;addr = addr->ai_next; } freeaddrinfo(servAddr); // Free addrinfo allocated in getaddrinfo() return sock;}int SetupTCPServerSocket(const char *service) { // Construct the server address structure struct addrinfo addrCriteria;// Criteria for address match memset(&addrCriteria, 0, sizeof(addrCriteria)); // Zero out structure addrCriteria.ai_family = AF_UNSPEC;// Any address family addrCriteria.ai_flags = AI_PASSIVE;// Accept on any address/port addrCriteria.ai_socktype = SOCK_STREAM;// Only stream sockets addrCriteria.ai_protocol = IPPROTO_TCP;// Only TCP protocol struct addrinfo *servAddr; // List of server addresses int rtnVal = getaddrinfo(NULL, service, &addrCriteria, &servAddr); if (rtnVal != 0)DieWithUserMessage("getaddrinfo() failed", gai_strerror(rtnVal)); int servSock = -1; struct addrinfo *addr = servAddr; while ( addr != NULL) {// Create a TCP socketservSock = socket(addr->ai_family, addr->ai_socktype,addr->ai_protocol);if (servSock < 0)continue;// Socket creation failed; try next address// Bind to the local address and set socket to listenif ((bind(servSock, addr->ai_addr, addr->ai_addrlen) == 0) &&(listen(servSock, MAXPENDING) == 0)) {// Print local address of socketstruct sockaddr_storage localAddr;socklen_t addrSize = sizeof(localAddr);if (getsockname(servSock, (struct sockaddr *) &localAddr, &addrSize) < 0)DieWithSystemMessage("getsockname() failed");fputs("Binding to ", stdout);PrintSocketAddress((struct sockaddr *) &localAddr, stdout);fputc(‘\n’, stdout);break;// Bind and listen successful}close(servSock); // Close and try againservSock = -1;addr = addr->ai_next; } // Free address list allocated by getaddrinfo() freeaddrinfo(servAddr); return servSock;}int AcceptTCPConnection(int servSock) { struct sockaddr_storage clntAddr; // Client address // Set length of client address structure (in-out parameter) socklen_t clntAddrLen = sizeof(clntAddr); // Wait for a client to connect int clntSock = accept(servSock, (struct sockaddr *) &clntAddr, &clntAddrLen); if (clntSock < 0)DieWithSystemMessage("accept() failed"); // clntSock is connected to a client! fputs("Handling client ", stdout); PrintSocketAddress((struct sockaddr *) &clntAddr, stdout); fputc(‘\n’, stdout); return clntSock;}void HandleTCPClient(int clntSocket) { char buffer[BUFSIZE]; // Buffer for echo string memset(buffer,0,sizeof(buffer)); // Receive message from client ssize_t numBytesRcvd = recv(clntSocket, buffer, BUFSIZE, 0); if (numBytesRcvd < 0)DieWithSystemMessage("recv() failed"); puts(buffer); putc(‘\n’,stdout); // Send received string and receive again until end of stream while (numBytesRcvd > 0) { // 0 indicates end of stream// Echo message back to clientssize_t numBytesSent = send(clntSocket, buffer, numBytesRcvd, 0);if (numBytesSent < 0)DieWithSystemMessage("send() failed");else if (numBytesSent != numBytesRcvd)DieWithUserMessage("send()", "sent unexpected number of bytes");// See if there is more data to receivenumBytesRcvd = recv(clntSocket, buffer, BUFSIZE, 0);if (numBytesRcvd < 0)DieWithSystemMessage("recv() failed"); } close(clntSocket); // Close client socket}

,没有朋友的人生是孤独的,不完整的,可是,因为生活的忙碌,

linux c socket之多进程任务

相关文章:

你感兴趣的文章:

标签云: