【Linux網路程式設計】基於TCP多程序(fork)版本客戶端/伺服器
客戶端程式碼:
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <string.h> #include <sys/types.h> #include <sys/socket.h> #include <arpa/inet.h> #include <netinet/in.h> static usage(const char* proc) { printf("%s [ip] [port\n]", proc); } int main(int argc, char** argv) { if(argc != 3) { usage(argv[0]); exit(1); } int sock = socket(AF_INET, SOCK_STREAM, 0); struct sockaddr_in server; if(sock < 0) { perror("socket"); return 1; } server.sin_family = AF_INET; server.sin_addr.s_addr = inet_addr(argv[1]); server.sin_port = htons(atoi(argv[2])); if(connect(sock ,(struct sockaddr*)&server, sizeof(server) ) < 0) { perror("connect"); exit(4); } char buf[1024]; while(1) { printf("please input #: "); fflush(stdout); ssize_t sread = read(0, buf, sizeof(buf)-1); if(sread > 0) { buf[sread-1] = 0; write(sock, buf, strlen(buf)); printf("server $ %s\n", buf); read(sock, buf, sizeof(buf) - 1); } } close(sock); }
服務端程式碼:
#include <stdio.h> #include <sys/types.h> // #include <sys/socket.h> // socket() bind() #include <unistd.h> #include <string.h> #include <stdlib.h> #include <arpa/inet.h> #include <netinet/in.h> // 使用幫助 static void usage(const char* proc) { printf("use help : %s [local_ip] [local_port]\n", proc); } // 建立並繫結一個socket int startup(const char* _ip, int _port) { // 建立一個socket int sock = socket(AF_INET, SOCK_STREAM, 0); if (sock < 0) { perror("----sock----fail\n"); exit(-1); } // 繫結一個本地socket struct sockaddr_in local; local.sin_family = AF_INET; local.sin_addr.s_addr = inet_addr(_ip); local.sin_port = htons(_port); if(bind(sock, (struct sockaddr*)&local, sizeof(local)) != 0) { perror("---bind---fail\n"); close(sock); exit(-2); } if(listen(sock, 5) != 0) { perror("----listen----fail\n"); close(sock); exit(-1); } return sock; } int main(int argc, char**argv) { if(argc != 3) { usage(argv[0]); return -1; } // 獲取一個local socket int listen_sock = startup(argv[1], atoi(argv[2])); struct sockaddr_in client; socklen_t len = sizeof(client); char buf[1024]; while(1) { int new_sock = accept(listen_sock,(struct sockaddr*)&client, &len); if(new_sock < 0) { perror("----accept----fail\n"); close(listen_sock); exit(-5); } pid_t id = fork(); if(id == 0) { // ///////////////可以再這裡fork 然後退出子程序,這樣負責監聽的程序PID就不會一直變////////// close(listen_sock); // 子程序已經獲得 sockfd, 不需要listen sock所以關閉 while(1) { ssize_t s = read(new_sock,buf, sizeof(buf)-1); if(s > 0 ) { buf[s] = 0; printf("client say## %s \n", buf); write(new_sock, buf, strlen(buf)); } else if( s == 0) { printf("client quit. \n"); break; } else break; } exit(0); } else if (id > 0) { // 父程序 // 在父程序中fork退出的話,會導致監聽程序的pid一直在變,所以我們也可以再子程序中fork然後退出 close(new_sock); // 此時子程序已經獲取 sockfd, 父程序只需要監聽sockfd,又因為每次fork都會賦值描述符,為了節省資源,關閉new_sock if(fork() > 0) { exit(0); } // 父程序退出,此時第二次fork出的子程序 成為孤兒程序,此後它產生的子程序退出時由系統來回收資源 } } return 0; }
截圖:
啟動服務端:
開啟一個終端檢視狀態可以看到已經在監聽:
然後啟動兩個客戶端模擬多個連線:
1.啟動客戶端1
2.然後檢視連線狀態,可以發現已經建立連線
然後再啟動一個程序,建立連線:
觀察狀態:
我們會發現負責Listen程序的的PID一直在變,是因為我們是在父程序中fork然後讓父程序退出,讓子程序繼續監聽,所以一直會變,我們可以使用一個小技巧,在子程序中fork一個程序,讓父程序不變。
相關推薦
【Linux網路程式設計】基於TCP多程序(fork)版本客戶端/伺服器
客戶端程式碼: #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <string.h> #include <sys/types.h
【Linux 網路程式設計】TCP網路程式設計中connect()、listen()和accept()三者之間的關係
基於 TCP 的網路程式設計開發分為伺服器端和客戶端兩部分,常見的核心步驟和流程如下: connect()函式:對於客戶端的 connect() 函式,該函式的功能為客戶端主動連線伺服器,建立連線是通過三次握手,而這個連接的過程是由核心完成,不是這個函式完成的,這個函式的作用僅僅是通知 Linux 核心
Socket網路程式設計:基於TCP多執行緒通訊
第一步:編寫啟動服務端的執行緒類 package socket; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.
Linux網路程式設計--IP地址與域名解析(DNS)
在日常生活中,人們往往知道主機的域名而不知道主機的IP地址,而socket的API均基於IP地址,所以需要使用DNS域名解析伺服器進行解析。 那麼首先簡單介紹一下DNS的原理,DNS伺服器系統是按樹形的結構構造,頂級域名伺服器下分多個二級域名伺服器,二級域名伺
【c++知識歸納】繼承與多型(一)
c++是基於面向物件的程式語言,面向物件的三大特性為:封裝、繼承和多型。本文對繼承與多型的知識點進行了總結歸納,這部分內容對於學習c++程式語言是非常重要的,文章加入我的個人理解,希望
【Android音視訊】Android Onvif-IPC開發(一)——在Android端搭建伺服器模擬Onvif-IP-Camera
Android端實現Onvif IPC開發: 本篇內容簡介: 本篇是上一文章移植失敗採取的第二方案,通過在android搭建service,模擬成一個onvif協議對接的IPC端,在這之前,首先需要明白,onvif裝置對接的流程或者說方式,接下來的文章內容
1、【網路程式設計】Socket/TCP/UDP/HTTP/HTTPS/網路分層模型
一、簡介 1、相關概念 TCP:傳送控制協議(Transmission Control Protocol) UDP:使用者資料報協議 (UDP:User Datagram Protocol) HTTP:全稱是HyperText Transfer Pro
【Unix 網路程式設計】TCP狀態轉換圖詳解
在前面,已經介紹了TCP協議的三路握手和四次揮手。如下圖所示,TCP通訊過程包括三個步驟:建立TCP連線通道(三次握手)、資料傳輸、斷開TCP連線通道(四次揮手)。
Linux網路程式設計---詳解TCP的三次握手和四次揮手
我們知道,在TCP/IP協議中,TCP協議提供可靠的連線服務,是因為它有許多保證可靠連線的機制。可以分為3個方面: 1.確認應答機制:指的是不管哪一端傳送資料都需要確認回覆一下。 2.超時重傳機制,傳送後等待一段時間,不管是傳送失敗或者是還沒有收到回覆,那麼就認為資料傳輸失敗了;此時將會
TCP/IP網路程式設計之基於TCP的服務端/客戶端
理解TCP和UDP 根據資料傳輸方式的不同,基於網路協議的套接字一般分為TCP套接字和UDP套接字。因為TCP套接字是面向連線的,因此又稱為基於流(stream)的套接字。TCP是Transmission Control Protocol(傳輸控制協議)的簡寫,意為“對資料傳
嵌入式Linux網路程式設計,I/O多路複用,epoll()示例,epoll()客戶端,epoll()伺服器,單鏈表
文章目錄 1,I/O多路複用 epoll()示例 1.1,epoll()---net.h 1.2,epoll()---client.c 1.3,epoll()---sever.c 1.4,epoll()---linklist.h
嵌入式Linux網路程式設計,I/O多路複用,poll()示例,poll()客戶端,poll()伺服器,單鏈表
文章目錄 1,IO複用poll()示例 1.1,poll()---net.h 1.2,poll()---client.c 1.3,poll()---sever.c 1.4,poll()---linklist.h 1.5,p
嵌入式Linux網路程式設計,I/O多路複用,select()示例,select()客戶端,select()伺服器,單鏈表
文章目錄 1,IO複用select()示例 1.1 select()---net.h 1.2 select()---client.c 1.3 select()---sever.c 1.4 select()---linklist.h
嵌入式Linux網路程式設計,I/O多路複用,阻塞I/O模式,非阻塞I/O模式fcntl()/ioctl(),多路複用I/O select()/pselect()/poll(),訊號驅動I/O
文章目錄 1,I/O模型 2,阻塞I/O 模式 2.1,讀阻塞(以read函式為例) 2.2,寫阻塞 3,非阻塞模式I/O 3.1,非阻塞模式的實現(fcntl()函式、ioctl() 函式)
【Java網路程式設計】:JDK API實現OIO和NIO
前言 網路程式設計是Java的一大難點,JDK自帶的api可以實現網路程式設計。 我們將從一個應用程式開始我們對傳輸的學習,這個應用程式只簡單地接受連線,然後向客戶端寫“Hi!”,然後關閉連線。 1. OIO實現 應用程式的阻塞(OIO)版程式碼如下: package
【Java網路程式設計】:Netty實現OIO和NIO
承接上文:https://blog.csdn.net/hxcaifly/article/details/85274664 前言 單純地使用Java JDK來實現網路NIO是一件開發成本非常高的事情。然而,Netty 為它所有的傳輸實現提供了一個通用API,這使得這種
《Linux網路程式設計》: TCP程式設計
TCP程式設計 TCP 程式設計的 C/S 架構 基於 TCP 的網路程式設計開發分為伺服器端和客戶端兩部分,常見的核心步驟和流程如下: TCP 客戶端程式設計 對於 TCP 客戶端程式設計流程,有點類似於打電話過程:找個可以通話的手機(socke
《Linux網路程式設計》: 埠複用(多個套接字繫結同一個埠)
在《繫結( bind )埠需要注意的問題》提到:一個網路應用程式只能繫結一個埠( 一個套接字只能繫結一個埠 )。 請檢視《Linux網路程式設計》: 繫結( bind )埠需要注意的問題 實際上,預設的情況下,如果一個網路應用程式的一個套接字 綁定了一個埠( 佔用了 80
【Java8網路程式設計】第3章. HTTP和URLConnection類
1.HTTP基本概念 HTTP(HyperText Transport Protocol)是超文字傳輸協議的縮寫,它用於傳送WWW方式的資料。HTTP協議採用了請求/響應模型。客戶端向伺服器傳送一個請求,請求頭包含請求的方法、URL、協議版本、以及包含請求修飾
【Linux 系統程式設計】常用的一些基本命令
前言 Linux提供了大量的命令,利用它可以有效地完成大量的工作,如磁碟操作、檔案存取、目錄操作、程序管理、檔案許可權設定等。所以,在Linux系統上工作離不開使用系統提供的命令。要想真正理解Linux系統,就必須從Linux命令學起,通過基礎的命令學