socket通信,server与多客户端通信

简介:
近日研究socket 通信,学习了如下的一篇文章:

http://blog.csdn.net/dlutcat/article/details/1813933

(向作者致敬)

感觉很好,但还有一点不过瘾,就想着能否加点料:增加多个客户端,让他们一起和服务器端通信。

为了区别各个客户端,把客户端里加入了识别自身hostname的一段。

修改后的代码如下:

server :

复制代码
#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);
   
    while (1){
        struct sockaddr_in client_addr;
        socklen_t length = sizeof(client_addr);

        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 Accept Failed!\n");
            break;
        }
        fprintf(stderr,"After accept. In %d.\n",getpid());

        int child_process_pid = fork();         
        if(child_process_pid == 0 ){

            fprintf(stderr,"Child. %d born.\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());
            close(new_server_socket);
            exit(0);        
        }
        else if(child_process_pid > 0)
            close(new_server_socket);
    }
    close(server_socket);
    return 0;
}
复制代码
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,两个跑client。先运行server,再分别跑两个client,结果如下:

为了方便观察,略作整理:

Server端运行结果:

复制代码
./con-server.o
Before Main Process listen.                    
After Main Process listen.                    
Before accept. In 676.                    
After accept. In 676                    
        Child 678 born.            
Before accept. In 676.                    
        got : post2.gao in 678            
After accept. In 676.                    
            Child 679 born.        
Before accept. In 676.                    
            got: post3.gao in 679.        
After accept. In 676.                    
                Child 680 born.    
Before accept. In 676.                    
                got: post2.gao in 680.    
After accept. In 676.                    
                    Child. 681 born.
Before accept. In 676.                    
                    got: post3.gao in 681
......
复制代码
两个client端运行结果:

./con-client.o  192.168.66.136                    
                    
From Server 192.168.66.136:  Hello,World! From Server! 678                    
From Server 192.168.66.136:  Hello,World! From Server! 680 
......                   
 

./con-client.o  192.168.66.136                    
                    
From Server 192.168.66.136:  Hello,World! From Server! 679                    
From Server 192.168.66.136:  Hello,World! From Server! 681 
......                   
这样就成为多个客户端请求Server端。

此外也可以发现,listen动作不阻塞,accept动作阻塞。

服务器端主进程每当捕获到一个客户端请求,就fork一个子进程,
由子进程用 new_server_socket来send 和 recv工作。

fork子进程后,工作完毕再消除的方法未必理想,今后有机会看看能否事先开一个进程池,来提升效率。








本文转自健哥的数据花园博客园博客,原文链接:http://www.cnblogs.com/gaojian/archive/2012/08/02/2618642.html,如需转载请自行联系原作者
目录
相关文章
|
1月前
|
Python
python socket 简单通信
python socket 简单通信
32 1
|
19天前
|
网络协议 安全 网络安全
网络编程:基于socket的TCP/IP通信。
网络编程:基于socket的TCP/IP通信。
111 0
|
11天前
|
网络协议 C# 开发者
WPF与Socket编程的完美邂逅:打造流畅网络通信体验——从客户端到服务器端,手把手教你实现基于Socket的实时数据交换
【8月更文挑战第31天】网络通信在现代应用中至关重要,Socket编程作为其实现基础,即便在主要用于桌面应用的Windows Presentation Foundation(WPF)中也发挥着重要作用。本文通过最佳实践,详细介绍如何在WPF应用中利用Socket实现网络通信,包括创建WPF项目、设计用户界面、实现Socket通信逻辑及搭建简单服务器端的全过程。具体步骤涵盖从UI设计到前后端交互的各个环节,并附有详尽示例代码,助力WPF开发者掌握这一关键技术,拓展应用程序的功能与实用性。
31 0
|
16天前
|
网络协议 Linux 应用服务中间件
Socket通信之网络协议基本原理
【8月更文挑战第27天】网络协议定义了机器间通信的标准格式,确保信息准确无损地传输。主要分为两种模型:OSI七层模型与TCP/IP模型。
|
23天前
|
网络协议
socket编程(2) -- TCP通信
socket编程(2) -- TCP通信
29 0
|
3月前
|
Java API 开发者
Java网络编程基础与Socket通信实战
Java网络编程基础与Socket通信实战
|
2月前
|
Java API 开发者
Java网络编程基础与Socket通信实战
Java网络编程基础与Socket通信实战
|
2月前
|
Java 数据格式
Java面试题:简述Java Socket编程的基本流程,包括客户端和服务器的创建与通信。
Java面试题:简述Java Socket编程的基本流程,包括客户端和服务器的创建与通信。
35 0
|
2月前
|
网络协议 安全 Java
深入了解Java中的网络编程与Socket通信
深入了解Java中的网络编程与Socket通信
|
2月前
|
网络协议 安全 Java
深入了解Java中的网络编程与Socket通信
深入了解Java中的网络编程与Socket通信