socket通信,server与多客户端通信(二)

简介:
接上回,socket通信,server与多客户端通信的文章。

搞一个先fork一堆子进程出来,再一起监听的server,client程序不变。

复制代码
#include<netinet/in.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<sys/signal.h>
#include<sys/wait.h>

#define HELLO_WORLD_SERVER_PORT    6666
#define LENGTH_OF_LISTEN_QUEUE 20
#define BUFFER_SIZE 1024

void reaper(int sig){
int status;
while(    wait3(&status,WNOHANG,(struct rusage*)0)  >=0   )
        ;
}

int main(int argc, char **argv){
    struct sockaddr_in server_addr;
    bzero(&server_addr,sizeof(server_addr));
    server_addr.sin_family = AF_INET;
    server_addr.sin_addr.s_addr = htons(INADDR_ANY);
    server_addr.sin_port = htons(HELLO_WORLD_SERVER_PORT);

    int server_socket = socket(AF_INET,SOCK_STREAM,0);
    if( server_socket < 0){
        printf("Create Socket Failed!");
        exit(1);
    }

    if( bind(server_socket,(struct sockaddr*)&server_addr,sizeof(server_addr))){
        printf("Server Bind Port : %d Failed!", HELLO_WORLD_SERVER_PORT);
        exit(1);
    }

    fprintf(stderr,"Before Main Process listen.\n");

    if ( listen(server_socket, LENGTH_OF_LISTEN_QUEUE) ){
        printf("Server Listen Failed!");
        exit(1);
    }
    fprintf(stderr, "After Main Process listen.\n");

(void)signal(SIGCHLD,reaper);
struct sockaddr_in client_addr;
socklen_t length = sizeof(client_addr);

int procnt;
for (procnt=0; procnt<10; procnt++){
        int child_process_pid = fork(); 
        if(child_process_pid == 0 ){
           fprintf(stderr,"Child %d is born",getpid());
           fprintf(stderr,"Before accept. In %d.\n",getpid());

           int new_server_socket = 
             accept(server_socket,(struct sockaddr*)&client_addr,&length);
           if ( new_server_socket < 0){
              printf("Server Child Accept Failed!\n");
              break;
           }
           fprintf(stderr,"After accept. In %d.\n",getpid());
           close(server_socket);

           char buffer[BUFFER_SIZE];
           bzero(buffer, BUFFER_SIZE);
           strcpy(buffer,"Hello,World! FromServer! ");

           int pd;
           pd=getpid();
           char cpd[10];
           sprintf(cpd,"%d",pd);
           strcat(buffer,cpd);
           strcat(buffer,"\n");            
           send(new_server_socket,buffer,BUFFER_SIZE,0);
           bzero(buffer,BUFFER_SIZE);

           length = recv(new_server_socket,buffer,BUFFER_SIZE,0);
           if (length < 0){
                printf("Server Recieve Data Failed!\n");
                exit(1);
           }
           fprintf(stderr,"got: %s in %d\n",buffer,getpid());

           //I should put here some rest dealings 
           //for current child process instead.
           //I will add it later.
           close(new_server_socket);
           exit(0);
      }else{
           //do nothing
      }
}

for(;;){
    sleep(10);
    fprintf(stderr,"I am main process waked from sleep.\n");
}

close(server_socket);
return 0;
}
复制代码
这样,client 和 server的通信,实际上就是server里面一群子进程在监听。谁逮住了谁响应。当然,这个进程池尚且有差距。今后再改进,考虑一次服务结束后,如何休眠和唤醒。

为了看着方便,把client的程序也放在这里:

复制代码
#include <netinet/in.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

#define HELLO_WORLD_SERVER_PORT    6666
#define BUFFER_SIZE 1024

void talk_to_server(char ** argv)
{   
    struct sockaddr_in client_addr;
    bzero(&client_addr,sizeof(client_addr));
    client_addr.sin_family = AF_INET;
    client_addr.sin_addr.s_addr = htons(INADDR_ANY);
    client_addr.sin_port = htons(0);

    int client_socket = socket(AF_INET,SOCK_STREAM,0);
    if( client_socket < 0){
        printf("Create Socket Failed!\n");
        exit(1);
    }
    
    if( bind(client_socket,(struct sockaddr*)&client_addr,sizeof(client_addr))){
        printf("Client Bind Port Failed!\n");
        exit(1);
    }

    struct sockaddr_in server_addr;
    bzero(&server_addr,sizeof(server_addr));
    server_addr.sin_family = AF_INET;

    if(inet_aton(argv[1],&server_addr.sin_addr) == 0){
        printf("Server IP Address Error!\n");
        exit(1);
    }
    server_addr.sin_port = htons(HELLO_WORLD_SERVER_PORT);
    socklen_t server_addr_length = sizeof(server_addr);

    if( 
      connect( client_socket, (struct sockaddr*)&server_addr, 
          server_addr_length) < 0){
        printf("Can Not Connect To %s!\n",argv[1]);
        exit(1);
    }

    char buffer[BUFFER_SIZE];
    bzero(buffer,BUFFER_SIZE);

    int length = recv(  client_socket,  buffer,BUFFER_SIZE,0);

    if(length < 0){
        printf("Recieve Data From Server %s Failed!\n", argv[1]);
        exit(1);
    }
    printf("From Server %s :\t%s",argv[1],buffer);

    bzero(buffer,BUFFER_SIZE);
    char name[64];
    gethostname(name,sizeof(name));
    strcpy(buffer,name);

    send(client_socket,buffer,BUFFER_SIZE,0);
    close(client_socket);
}

int main(int argc, char **argv)
{
    if (argc != 2){
        printf("Usage: ./%s ServerIPAddress\n",argv[0]);
        exit(1);
    }

    int i=0;
    for(i=0; i<10000; i++){
        talk_to_server(argv);
        sleep(10);
    }
    return 0;
}
复制代码
server端运行结果如下:

复制代码
Before Main Process listen.
After Main Process listen.

Child 3882 is bornBefore accept. In 3882.
Child 3883 is bornBefore accept. In 3883.
Child 3884 is bornBefore accept. In 3884.
Child 3885 is bornBefore accept. In 3885.
Child 3886 is bornBefore accept. In 3886.
Child 3887 is bornBefore accept. In 3887.
Child 3888 is bornBefore accept. In 3888.
Child 3889 is bornBefore accept. In 3889.
Child 3890 is bornBefore accept. In 3890.
Child 3891 is bornBefore accept. In 3891.

I am mian process waked from sleep.
I am mian process waked from sleep.
I am mian process waked from sleep.

After accept. In 3882
got: post2.gao in 3882

After accept. In 3883
got: post2.gao in 3883

After accept. In 3884
got: post2.gao in 3884

After accept. In 3885
got: post2.gao in 3885

After accept. In 3886
got: post2.gao in 3886

After accept. In 3887
got: post2.gao in 3887

After accept. In 3888
got: post2.gao in 3888

After accept. In 3889
got: post2.gao in 3889

After accept. In 3890
got: post2.gao in 3890

After accept. In 3891
got: post2.gao in 3891


I am mian process waked from sleep.
I am mian process waked from sleep.
I am mian process waked from sleep.
I am mian process waked from sleep.









本文转自健哥的数据花园博客园博客,原文链接:http://www.cnblogs.com/gaojian/archive/2012/08/03/2620964.html,如需转载请自行联系原作者
目录
相关文章
|
12天前
|
存储 Python
Python网络编程基础(Socket编程)UDP客户端编程
【4月更文挑战第9天】在UDP通信中,客户端负责发送数据到服务器,并接收来自服务器的响应。与服务器不同,客户端通常不需要绑定到特定的地址和端口,因为它可以临时使用任何可用的端口来发送数据。下面,我们将详细讲解UDP客户端编程的基本步骤。
|
12天前
|
网络协议 程序员 Python
pythonTCP客户端编程创建Socket对象
【4月更文挑战第6天】本教程介绍了TCP客户端如何创建Socket对象。Socket作为网络通信的基础单元,包含协议、IP地址和端口等信息。在TCP/IP中,Socket分为流式(TCP)、数据报(UDP)和原始套接字。以Python为例,创建TCP Socket对象需调用`socket.socket(AF_INET, SOCK_STREAM)`。为确保健壮性,应使用异常处理处理可能的`socket.error`。学习本教程将帮助你掌握TCP客户端创建Socket对象的技能。
|
12天前
|
网络协议 Python
python中socket客户端发送和接收数据
【4月更文挑战第7天】本教程聚焦TCP客户端数据发送与接收。使用Python的`socket`模块,通过`send()`发送字节串至服务器,如`client_socket.send(message_bytes)`;用`recv()`接收数据,如`received_data = client_socket.recv(buffer_size)`。异常处理确保网络错误时程序健壮性,例如`try-except`捕获`socket.error`。理解和掌握这些基础操作对于构建稳定的TCP客户端至关重要。
|
12天前
|
网络协议 安全 Python
python中socket客户端关闭连接
【4月更文挑战第7天】本教程介绍了如何在TCP客户端中正确关闭连接。使用`close()`方法可关闭Socket连接并释放资源,示例代码显示了在正常和异常情况下关闭连接的方法。注意异常处理以确保在任何情况下都能关闭连接,并避免并发操作同一Socket,以保证连接的稳定和安全。掌握这些技巧对编写健壮的TCP客户端至关重要。
|
2天前
|
设计模式 监控 网络协议
socket通信处于网络协议那一层和两种接收发送消息方式
socket通信处于网络协议那一层和两种接收发送消息方式
10 2
|
5天前
|
监控 Unix Linux
采用异步socket实现客户端和服务端的通信
采用异步socket实现客户端和服务端的通信
11 0
|
12天前
|
XML JSON 网络协议
Socket实现模拟TCP通信粘包问题
Socket实现模拟TCP通信粘包问题
|
12天前
|
网络协议
Socket实现服务器和客户端(手把手教会)
Socket实现服务器和客户端(手把手教会)
|
12天前
|
Java 开发者 Spring
Java一分钟之-Java网络编程基础:Socket通信
【5月更文挑战第13天】本文介绍了Java Socket编程基础知识,包括使用`ServerSocket`和`Socket`类建立连接,通过`OutputStream`和`InputStream`进行数据传输。常见问题涉及忘记关闭Socket导致的资源泄漏、网络异常处理及并发同步。理解Socket通信原理并掌握异常处理、资源管理和并发控制,能帮助开发者构建更稳定的网络应用。
37 1
|
12天前
|
网络协议 Java 网络安全
【计算机网络】—— Socket通信编程与传输协议分析
【计算机网络】—— Socket通信编程与传输协议分析