1. 程式人生 > >【Linux網路程式設計】基於TCP多程序(fork)版本客戶端/伺服器

【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命令學起,通過基礎的命令學