多進程伺服器Demo

来源:http://www.cnblogs.com/General-up/archive/2016/04/30/5449729.html
-Advertisement-
Play Games

今天實現的這個伺服器程式加入了對多個客戶端同時請求處理的實現,伺服器端通過對每次監聽到的客戶端程式新建一個子進程,進行相關的處理,將從客戶端傳來的字元串數據,轉化為大寫的字元串序列,然重新寫回到connfd;另一方面,客戶端通過在標準輸入里獲取客戶輸入到的字元串序列,傳送到connfd,再從conn ...


  今天實現的這個伺服器程式加入了對多個客戶端同時請求處理的實現,伺服器端通過對每次監聽到的客戶端程式新建一個子進程,進行相關的處理,將從客戶端傳來的字元串數據,轉化為大寫的字元串序列,然重新寫回到connfd;另一方面,客戶端通過在標準輸入里獲取客戶輸入到的字元串序列,傳送到connfd,再從connfd讀取經伺服器處理過的字元串序列列印到標準輸出上。

  同時,加上了對某些socket原語函數的封裝處理,主要封裝了對出錯的處理機制,基本原語函數都以相應大寫首個字元的命名錶示,定義在“wrap.c”和“wrap.h”文件中。

wrap.h

  1 /* wrap.h */
  2 #ifndef __WRAP_H_
  3 #define __WRAP_H_
  4 
  5 void perr_exit(const char *s);
  6 int Accept(int fd, struct sockaddr *sa, socklen_t *salenptr);
  7 void Bind(int fd, const struct sockaddr *sa, socklen_t salen);
  8 void Connect(int fd, const struct sockaddr *sa, socklen_t salen);
  9 void Listen(int fd, int backlog);
 10 int Socket(int family, int type, int protocol);
 11 ssize_t Read(int fd, void *ptr, size_t nbytes);
 12 ssize_t Write(int fd, const void *ptr, size_t nbytes);
 13 void Close(int fd);
 14 ssize_t Readn(int fd, void *vptr, size_t n);
 15 ssize_t Writen(int fd, const void *vptr, size_t n);
 16 static ssize_t my_read(int fd, char *ptr);
 17 ssize_t Readline(int fd, void *vptr, size_t maxlen);
 18 
 19 #endif

 

wrap.c

  1 /*wrap.c */
  2 #include<stdlib.h>
  3 #include<errno.h>
  4 #include<sys/socket.h>
  5 
  6 void perr_exit(const char* s)
  7 {
  8     perror(s);
  9     exit(1);
 10 }
 11 
 12 int Accept(int fd,struct sockaddr *sa,socklen_t *salenptr)
 13 {
 14     int n;
 15 again:
 16     if((n=accept(fd,sa,salenptr))<0){
 17         if((errno==ECONNABORTED)||(errno==EINTR))
 18             goto again;
 19         else
 20             perr_exit("accept error");
 21     }
 22     return n;
 23 }
 24 
 25 void Bind(int fd,const struct sockaddr *sa,socklen_t salen)
 26 {
 27     if(bind(fd,sa,salen)<0)
 28         perr_exit("bind error");
 29 }
 30 
 31 void Connect(int fd,const struct sockaddr *sa,socklen_t salen)
 32 {
 33     if(connect(fd,sa,salen)<0)
 34         perr_exit("connect error");
 35 }
 36 
 37 void Listen(int fd,int backlog)
 38 {
 39     if(listen(fd,backlog)<0)
 40         perr_exit("listen error");
 41 }
 42 
 43 int Socket(int family,int type,int protocol)
 44 {
 45     int n;
 46     if((n=socket(family,type,protocol))<0)
 47         perr_exit("socket error");
 48     return n;
 49 }
 50 
 51 ssize_t Read(int fd,void *ptr,size_t nbytes)
 52 {
 53     ssize_t n;
 54 again:
 55     if((n=read(fd,ptr,nbytes))==-1){
 56         if(errno==EINTR)
 57             goto again;
 58         else
 59             return -1;
 60     }
 61     return n;
 62 }
 63
 64 ssize_t Write(int fd,const void *ptr,size_t nbytes)
 65 {   
 66     ssize_t n;
 67 again:
 68     if((n=write(fd,ptr,nbytes))==-1){
 69         if(errno==EINTR)
 70             goto again;
 71         else
 72             return -1;
 73     }
 74     return n;
 75 }
 76 
 77 void Close(int fd)
 78 {   
 79     if(close(fd)==-1)
 80         perr_exit("close error");
 81 }
 82 
 83 ssize_t Readn(int fd,void *vptr,ssize_t n)
 84 {   
 85     size_t nleft;
 86     ssize_t nread;
 87     char *ptr;
 88     ptr=vptr;
 89     nleft=n;
 90     while(nleft>0){
 91         if((nread=read(fd,ptr,nleft))<0){
 92             if(errno==EINTR)
 93                 nread=0;
 94             else
 95                 return -1;
 96         }else if(nread==0)
 97             break;
 98         nleft-=nread;
 99         ptr+=nread;
100     }
101     return n-nleft;
102 }
103 
104 
105 ssize_t Writen(int fd,const void *vptr,size_t n)
106 {
107     size_t nleft;
108     ssize_t nwritten;
109     const char* ptr;
110     ptr=vptr;
111     nleft=n;
112     while(nleft>0){
113         if(nwritten=write(fd,ptr,nleft)<=0){
114             if(nwritten<0&&errno==EINTR)
115                 nwritten=0;
116             else
117                 return -1;
118         }
119         nleft-=nwritten;
120         ptr+=nwritten;
121     }
122     return n;
123 }
124 
125 static ssize_t my_read(int fd,char* ptr)
126 {
127     static int read_cnt;
128     static char *read_ptr;
129     static char read_buf[100];
130     if(read_cnt<=0){
131 again:
132         if((read_cnt=read(fd,read_buf,sizeof(read_buf)))<0){
133             if(errno==EINTR)
134                 goto again;
135             else
136                 return -1;
137         }else if(read_cnt==0)
138             return 0;
139         read_ptr=read_buf;
140     }
141     read_cnt--;
142     *ptr=*read_ptr++;
143     return 1;
144 }
145 
146 ssize_t Readline(int fd,void *vptr,size_t maxlen)
147 {
148     ssize_t n,rc;
149     char c,*ptr;
150     ptr=vptr;
151     for(n=1;n<maxlen;n++){
152         if((rc=my_read(fd,&c))==1){
153             *ptr++=c;
154             if(c=='\n')
155                 break;
156         }else if(rc==0){
157             *ptr=0;
158             return n-1;
159         }else
160             return -1;
161     }
162     *ptr=0;
163     return n;
164 }
165 

 

伺服器端:

  1 #include<stdlib.h>
  2 #include<stdio.h>
  3 #include<unistd.h>
  4 #include<string.h>
  5 #include<netinet/in.h>
  6 #include<sys/types.h>
  7 #include<sys/socket.h>
  8 #include<arpa/inet.h>
  9 #include "wrap.c"
 10 #define SERVER_PORT 8000
 11 #define BUFSIZE 80
 12 int main(int argc,char* argv[])
 13 {
 14     struct sockaddr_in serveraddr,clientaddr;
 15     int listenfd,connfd,len,clientaddr_len,i;
 16     char buf[BUFSIZE];
 17     char str[BUFSIZE];
 18     pid_t pid;
 19     listenfd=Socket(AF_INET,SOCK_STREAM,0);
 20 
 21     bzero(&serveraddr,sizeof(serveraddr));
 22     serveraddr.sin_family=AF_INET;
 23     serveraddr.sin_addr.s_addr=htonl(INADDR_ANY);
 24     serveraddr.sin_port=htons(SERVER_PORT);
 25 
 26     Bind(listenfd,(struct sockaddr *)&serveraddr,sizeof(serveraddr));
 27 
 28     Listen(listenfd,128);
 29     printf("waiting for connecting\n");
 30     while(1){
 31         clientaddr_len=sizeof(clientaddr);
 32         connfd=Accept(listenfd,(struct sockaddr *)&clientaddr,&clientaddr_len);
 33         printf("client ip: %s\tport :%d\n",inet_ntop(AF_INET,&clientaddr.sin_addr.s_addr,str,sizeof(str)),ntohs(clientaddr.sin_port));
 34         pid=fork();
 35         if(pid==0){
 36                 Close(listenfd);
 37                 while(1){
 38                     len=Read(connfd,buf,sizeof(buf));
 39                     for(i=0;i<len;i++)
 40                         buf[i]=toupper(buf[i]);
 41                     Write(connfd,buf,len);
 42                 }
 43                 Close(connfd);
 44                 return 0;
 45         }else if(pid>0){
 46                 Close(connfd);
 47         }
 48         else{
 49             //error deal
 50         }
 51     }
 52 //  Close(listenfd);
 53     return 0;
 54 }

客戶端:

  1 #include<stdlib.h>
  2 #include<stdio.h>
  3 #include<string.h>
  4 #include<sys/types.h>
  5 #include<netinet/in.h>
  6 #include<sys/socket.h>
  7 #include<unistd.h>
  8 #include "wrap.c"
  9 #define SERVER_PORT 8000
 10 #define BUFSIZE 80
 11 int main(int argc,char* argv[])
 12 {
 13     int confd,len;
 14     struct sockaddr_in serveraddr;
 15     confd=Socket(AF_INET,SOCK_STREAM,0);
 16     char buf[BUFSIZE];
 17 
 18     bzero(&serveraddr,sizeof(serveraddr));
 19     serveraddr.sin_family=AF_INET;
 20     inet_pton(AF_INET,"127.0.0.1",&serveraddr.sin_addr.s_addr);
 21     serveraddr.sin_port=htons(SERVER_PORT);
 22 
 23     Connect(confd,(struct sockaddr*)&serveraddr,sizeof(serveraddr));
 24     while(fgets(buf,sizeof(buf),stdin)){
 25         Write(confd,buf,strlen(buf));
 26         len=Read(confd,buf,BUFSIZE);
 27         printf("the result from server:\n");
 28         Write(STDOUT_FILENO,buf,len);
 29     }
 30 
 31     Close(confd);
 32     return 0;
 33 }

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • SQL Server 2008有180天的試用期,過期後會提示“評估期已過”的提示。 1、進入SQL Server安裝中心: 2、選擇“維護”-“版本升級” 3、輸入密鑰: 其他的根據提示操作。 附SQL Server序列號: 開發版: PTTFM-X467G-P7RH2-3Q6CG-4DMYB企業 ...
  • 使用dbca建庫時遇到ORA-01501: CREATE DATABASE failed這個錯誤,檢查告警日誌,發現有下麵錯誤信息: SMON: enabling tx recoveryFri Apr 29 14:06:25 HKT 2016replication_dependency_tracki... ...
  • 1.使用theano調用relu激活函數提示''It looks like your version of theano is out of date'' bug信息顯然是提示更新theano版本,可是一看官網最新版本就是0.7.0,使用pip更新後也提示已經是最新版本。 經過檢查後發現,原來the ...
  • 在保密你的伺服器和數據,防備當前複雜的攻擊,SQL Server有你需要的一切。但在你能有效使用這些安全功能前,你需要理解你面對的威脅和一些基本的安全概念。這篇文章提供了基礎,因此你可以對SQL Server里的安全功能充分利用,不用在面對特定威脅,不能保護你數據的功能上浪費時間。 SQL Serv ...
  • 前一段時間學習netcore的時候解除到了docker,感覺真是不錯的技術。百度了不少教程。因為我用windows就下載安裝了一下試試。但是沒有安裝成功,才發現 需要安裝virtualbox虛擬機,與我的hyper-v衝突。後來看新聞出了windows版的docker,把virtualbox換成了h ...
  • 由於要經常使用終(zhuang)端(bi),每次打開是醬嬸兒滴: 或者進入幾級目錄之後,變成醬紫了: 真××醜!而且隨便輸幾個命令就換行好麽!怎麼辦呢?很簡單,分兩步: STEP1: 修改電腦名 如上截圖中,“@”和“:”之間的就是主機名了,即Chris-Laptop-Thinkpad-X240, ...
  • 下載:mysql-connector-java-5.1.38.tar.gz http://dev.mysql.com/downloads/connector/j/ tar zxvf mysql-connector-java-5.1.38.tar.gz 解壓後 zhousp@ubuntu:~/Down ...
  • 如果安裝的是中文版Ubuntu,那麼/home下的目錄會是“桌面”“下載”等,在終端下進入這些目錄看起來很不爽,那怎樣改為英文目錄呢,很簡單: STEP1: 將這些目錄修改為英文名,如: mv 桌面 Desktop STEP2: 修改配置文件 ~/.config/user-dirs.dirs ,將對 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...