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,如需转载请自行联系原作者
目录
相关文章
|
3月前
|
Python
python socket 简单通信
python socket 简单通信
43 1
|
3月前
|
网络协议 安全 网络安全
网络编程:基于socket的TCP/IP通信。
网络编程:基于socket的TCP/IP通信。
240 0
|
1月前
|
Python
Socket学习笔记(二):python通过socket实现客户端到服务器端的图片传输
使用Python的socket库实现客户端到服务器端的图片传输,包括客户端和服务器端的代码实现,以及传输结果的展示。
139 3
Socket学习笔记(二):python通过socket实现客户端到服务器端的图片传输
|
1月前
|
JSON 数据格式 Python
Socket学习笔记(一):python通过socket实现客户端到服务器端的文件传输
本文介绍了如何使用Python的socket模块实现客户端到服务器端的文件传输,包括客户端发送文件信息和内容,服务器端接收并保存文件的完整过程。
149 1
Socket学习笔记(一):python通过socket实现客户端到服务器端的文件传输
|
1月前
|
网络协议 Linux 应用服务中间件
Socket通信之网络协议基本原理
【10月更文挑战第10天】网络协议定义了机器间通信的标准格式,确保信息准确无损地传输。主要分为两种模型:OSI七层模型与TCP/IP模型。
|
2月前
|
网络协议 Linux 应用服务中间件
Socket通信之网络协议基本原理
【9月更文挑战第14天】网络协议是机器间交流的约定格式,确保信息准确传达。主要模型有OSI七层与TCP/IP模型,通过分层简化复杂网络环境。IP地址全局定位设备,MAC地址则在本地网络中定位。网络分层后,数据包层层封装,经由不同层次协议处理,最终通过Socket系统调用在应用层解析和响应。
|
2月前
|
关系型数据库 MySQL 数据库
docker启动mysql多实例连接报错Can’t connect to local MySQL server through socket ‘/var/run/mysqld/mysqld.sock’
docker启动mysql多实例连接报错Can’t connect to local MySQL server through socket ‘/var/run/mysqld/mysqld.sock’
186 0
|
3月前
|
网络协议 C# 开发者
WPF与Socket编程的完美邂逅:打造流畅网络通信体验——从客户端到服务器端,手把手教你实现基于Socket的实时数据交换
【8月更文挑战第31天】网络通信在现代应用中至关重要,Socket编程作为其实现基础,即便在主要用于桌面应用的Windows Presentation Foundation(WPF)中也发挥着重要作用。本文通过最佳实践,详细介绍如何在WPF应用中利用Socket实现网络通信,包括创建WPF项目、设计用户界面、实现Socket通信逻辑及搭建简单服务器端的全过程。具体步骤涵盖从UI设计到前后端交互的各个环节,并附有详尽示例代码,助力WPF开发者掌握这一关键技术,拓展应用程序的功能与实用性。
117 0
|
3月前
|
网络协议
socket编程(2) -- TCP通信
socket编程(2) -- TCP通信
43 0
|
4月前
|
Java API 开发者
Java网络编程基础与Socket通信实战
Java网络编程基础与Socket通信实战