16、并发服务器

news/2024/5/17 16:57:10 标签: 服务器, socket, struct, buffer, server, tcp
 

              UDP并发服务器

              UDP循环服务器实现的方法:

              UDP服务器每次从套接字上读取一个客户端的请求,接着处理,然后将结果返回给客户机。

              socket();

              bind();

              while(1)

              {

                     recvfrom();

                     process();

                     sendto();

              }

 

                                   TCP循环服务器

              TCP循环服务器接受一个客户端的连接,然后处理,完成了这个客户的所有请求后,断开连接:

                     socket();

                     bind();

                     listen();

                     while(1)

                            {

                                   accept();

                                   process();

                                   close();

                            }

 

              TCP循环服务器一次只能处理一个客户端的请求。只有在这个客户端的所有请求都满足后,服务器才可以继续后面的请求。这样如果有一个客户端占住服务器不放时,其他的客户机都不能工作了,因此,TCP服务器一般很少用循环 服务器模型

 

                                   TCP并发服务器(循环服务器改造的)

              并发服务器的思想是每一个客户机的请求并不由服务器直接处理,而是服务器创建一个子进程来处理

              socket();

              bind();

              listen();

              while(1)

                     {

                            accept();

                            if(fork()==0)

                            {

                                   process();

                                   close();

                                   exit();

                                   }

                                   close();

                     }

 

 

 

                     例题:TCP并发服务器

                                                

                                  Tcp_server_fork.c

#include <stdlib.h>

#include <stdio.h>

#include <errno.h>

#include <string.h>

#include <netdb.h>

#include <sys/types.h>

#include <netinet/in.h>

#include <sys/socket.h>

 

#define MY_PORT 3333

 

int main(int argc ,char **argv)

{

 int listen_fd,accept_fd;

 struct sockaddr_in     client_addr;

 int n;

 

 if((listen_fd=socket(AF_INET,SOCK_STREAM,0))<0)

  {

        printf("Socket Error:%s\n\a",strerror(errno));

        exit(1);

  }

 

 bzero(&client_addr,sizeof(struct sockaddr_in));

 client_addr.sin_family=AF_INET;

 client_addr.sin_port=htons(MY_PORT);

 client_addr.sin_addr.s_addr=htonl(INADDR_ANY);

 n=1;

 /* 如果服务器终止后,服务器可以第二次快速启动而不用等待一段时间  */

 setsockopt(listen_fd,SOL_SOCKET,SO_REUSEADDR,&n,sizeof(int));

 if(bind(listen_fd,(struct sockaddr *)&client_addr,sizeof(client_addr))<0)

  {

        printf("Bind Error:%s\n\a",strerror(errno));

        exit(1);

  }

  listen(listen_fd,5);

  while(1)

  {

   accept_fd=accept(listen_fd,NULL,NULL);

   if((accept_fd<0)&&(errno==EINTR))

          continue;

   else if(accept_fd<0)

    {

        printf("Accept Error:%s\n\a",strerror(errno));

        continue;

    }

  if((n=fork())==0)

   {

        /* 子进程处理客户端的连接 */

        char buffer[1024];

 

        close(listen_fd);

        n=read(accept_fd,buffer,1024);

        write(accept_fd,buffer,n);

        close(accept_fd);

        exit(0);

   }

   else if(n<0)

        printf("Fork Error:%s\n\a",strerror(errno));

   close(accept_fd);

  }

}

 

 

 

 

 

                                                 Tcp_client.c

#include <stdlib.h>

#include <stdio.h>

#include <errno.h>

#include <string.h>

#include <netdb.h>

#include <sys/types.h>

#include <netinet/in.h>

#include <sys/socket.h>

 

#define portnumber 3333

 

int main(int argc, char *argv[])

{

    int sockfd;

    char buffer[1024];

    struct sockaddr_in server_addr;

    struct hostent *host;

 

        /* 使用hostname查询host 名字 */

    if(argc!=2)

    {

        fprintf(stderr,"Usage:%s hostname \a\n",argv[0]);

        exit(1);

    }

 

    if((host=gethostbyname(argv[1]))==NULL)

    {

        fprintf(stderr,"Gethostname error\n");

        exit(1);

    }

 

    /* 客户程序开始建立 sockfd描述符 */

    if((sockfd=socket(AF_INET,SOCK_STREAM,0))==-1) // AF_INET:Internet;SOCK_STREAM:TCP

    {

        fprintf(stderr,"Socket Error:%s\a\n",strerror(errno));

        exit(1);

    }

 

    /* 客户程序填充服务端的资料 */

    bzero(&server_addr,sizeof(server_addr)); // 初始化,置0

    server_addr.sin_family=AF_INET;          // IPV4

    server_addr.sin_port=htons(portnumber);  // (将本机器上的short数据转化为网络上的short数据)端口号

    server_addr.sin_addr=*((struct in_addr *)host->h_addr); // IP地址

   

    /* 客户程序发起连接请求 */

    if(connect(sockfd,(struct sockaddr *)(&server_addr),sizeof(struct sockaddr))==-1)

    {

        fprintf(stderr,"Connect Error:%s\a\n",strerror(errno));

        exit(1);

    }

 

    /* 连接成功了 */

    printf("Please input char:\n");

   

    /* 发送数据 */

    fgets(buffer,1024,stdin);

    write(sockfd,buffer,strlen(buffer));

 

    /* 结束通讯 */

    close(sockfd);

    exit(0);

}

 

 


http://www.niftyadmin.cn/n/1262349.html

相关文章

UNP Chapter 23 - 线程

23.1. 概述 在传统的UNIX模型中&#xff0c;当一个进程需要由另一个实体执行某件事时&#xff0c;该进程派生(fork)一个子进程&#xff0c;让子进程去进行处理。UNIX下的大多数网络服务器程序都是这么编写的&#xff0c;这在我们的并发服务程序例子中可以看出&#xff1a;父进程…

linux下的framebuffer(1)

概念&#xff1a; 1、像素&#xff1a;pixel,点阵&#xff0c;就是屏幕上的一个点。 2、Bpp:每个像素所占的bit数。bit数越大&#xff0c;一个像素能表现颜色数越多。8bpp&#xff0c;能表现256种颜色。16Bpp能表现65536种颜色。 3、分辨率&#xff1a;一个屏幕x方向和y方向…

PL/SQL函数笔记

-----函数总结: --一,数字函数: --abs(n):用于返回n的绝对值declare v_abs number(6, 2);begin v_abs : abs(&no); dbms_output.put_line(绝对值: || v_abs);end;select abs(-34) from dual; ---exp(n):返回e的n次幂(e2.71828183...).declare v_exp number(6, 2);begin v_e…

linux下的framebuffer(2)

目前根据自己对linux中framebuffer的了解写了如下的代码&#xff1a; 下面是用到的一些文件&#xff0c;在linux下编译通过&#xff0c;显示图形效果。 效果&#xff1a;主要代码在fb.c中&#xff0c;在显卡x,y(1100,100)出显示x0,y0(130,150)大小的颜色&#xff0c;再在x0,y0…

MVVM之Event and Command

Event&#xff1a; 在Silverlight和WPF中没有使用.net的LCR事件&#xff0c;而是使用Routed路由事件&#xff0c;根本原因是因为Silverlight控件的节点树。 一个简单的示例&#xff1a; public static readonly RoutedEvent MyRoutedEvent EventManager.RegisterRoutedEvent(&…

js和as的稳定传值问题

最近在实现flash的播放音乐的功能&#xff0c;这就涉及到js和as交互的问题&#xff0c;因为要实现动态改变音乐文件的功能。但是在实现js传值给flash时&#xff0c;flash在获取值存在几率性&#xff0c;有时可以获得到&#xff0c;有时有获取不到。后来发现&#xff0c;其实是由…

linux内核struct链表程序与分析

struct是编程的重要部分&#xff0c;学好struct非常重要&#xff0c;本文参考网友与自己总结&#xff0c;适合初学者&#xff0c;或者想了解linux内核对struct的利用。 编写的代码在linux下gcc可编译通过。 # gcc mylist.c -o mylist [jinyonglocalhost 888]$ lslist.h myli…

Windows消息+GlobalAddAtom 实现两程序通信

WinAPI: AddAtom、DeleteAtom、FindAtom、GetAtomName、GlobalAddAtom、GlobalDeleteAtom、GlobalFindAtom、GlobalGetAtomName这是储存字符串的一组 API.通过 AddAtom 储存一个字符串, 返回一个 ID;GetAtomName 通过这个 ID 可返回储存的字符串;还可以用 FindAtom 查找、用 De…