1. 程式人生 > >linux多程序伺服器示例

linux多程序伺服器示例

伺服器端

#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>

#define ERR_EXIT(m) \
        do \
        { \
                perror(m); \
                exit(EXIT_FAILURE); \
        } while(0)

struct packet
{
	int len;
	char buf[1024];
};

//1一次全部讀走 //2次讀完資料 //出錯分析 //對方已關閉
//思想:tcpip是流協議,不能保證1次讀操作,能全部把報文讀走,所以要迴圈讀指定長度的資料。
//按照count大小讀資料,
//若讀取的長度ssize_t<count 說明讀到了一個結束符,對方已關閉。

//@ssize_t:返回讀的長度 若ssize_t<count 讀失敗失敗
//@buf:接受資料記憶體首地址
//@count:接受資料長度
ssize_t readn(int fd, void *buf, size_t count)
{
	size_t nleft = count;
	ssize_t nread;
	char *bufp = (char*)buf;

	while (nleft > 0)
	{
		if ((nread = read(fd, bufp, nleft)) < 0)
		{
			if (errno == EINTR)
				continue;
			return -1;
		}
		else if (nread == 0) //若對方已關閉
			return count - nleft;

		bufp += nread;
		nleft -= nread;
	}

	return count;
}

//1一次全部讀走 //2次讀完資料 //出錯分析 //對方已關閉
//思想:tcpip是流協議,不能1次把指定長度資料,全部寫完 
//按照count大小寫資料
//若讀取的長度ssize_t<count 說明讀到了一個結束符,對方已關閉。
//@ssize_t:返回寫的長度 -1失敗
//@buf:待寫資料首地址
//@count:待寫長度

ssize_t writen(int fd, const void *buf, size_t count)
{
	size_t nleft = count;
	ssize_t nwritten;
	char *bufp = (char*)buf;

	while (nleft > 0)
	{
		if ((nwritten = write(fd, bufp, nleft)) < 0)
		{
			if (errno == EINTR)
				continue;
			return -1;
		}
		else if (nwritten == 0)
			continue;

		bufp += nwritten;
		nleft -= nwritten;
	}

	return count;
}

void do_service(int conn)
{
	struct packet recvbuf;
	int n;
    while (1)
	{
        memset(&recvbuf, 0, sizeof(recvbuf));
        int ret = readn(conn, &recvbuf.len, 4); //讀包頭 4個位元組
		if (ret == -1)
			ERR_EXIT("read");
		else if (ret < 4)
		{
			printf("client close\n");
			break;
		}
		
		n = ntohl(recvbuf.len);
		ret = readn(conn, recvbuf.buf, n); //根據長度讀資料
		if (ret == -1)
			ERR_EXIT("read");
		else if (ret < n)
		{
			printf("client close\n");
			break;
		}
		
	    fputs(recvbuf.buf, stdout);
	   
	    writen(conn, &recvbuf, 4+n);  //注意寫資料的時候,多加4個位元組
	}
}

int main(void)
{
	int listenfd;
	if ((listenfd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
/*	if ((listenfd = socket(PF_INET, SOCK_STREAM, 0)) < 0)*/
		ERR_EXIT("socket");

	struct sockaddr_in servaddr;
	memset(&servaddr, 0, sizeof(servaddr));
	servaddr.sin_family = AF_INET;
	servaddr.sin_port = htons(8001);
	servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
	/*servaddr.sin_addr.s_addr = inet_addr("127.0.0.1");*/
	/*inet_aton("127.0.0.1", &servaddr.sin_addr);*/

	int on = 1;
	if (setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0)
		ERR_EXIT("setsockopt");

	if (bind(listenfd, (struct sockaddr*)&servaddr, sizeof(servaddr)) < 0)
		ERR_EXIT("bind");
	if (listen(listenfd, SOMAXCONN) < 0)
		ERR_EXIT("listen");

	struct sockaddr_in peeraddr;
	socklen_t peerlen = sizeof(peeraddr);
	int conn;

	pid_t pid;
	while (1)
	{
		if ((conn = accept(listenfd, (struct sockaddr*)&peeraddr, &peerlen)) < 0)
			ERR_EXIT("accept");

		printf("ip=%s port=%d\n", inet_ntoa(peeraddr.sin_addr), ntohs(peeraddr.sin_port));

		pid = fork();
		if (pid == -1)
			ERR_EXIT("fork");
		if (pid == 0)
		{
			close(listenfd);
			do_service(conn);
			exit(EXIT_SUCCESS);
		}
		else
			close(conn);
	}
	
	return 0;
}

客戶端

#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>

#define ERR_EXIT(m) \
        do \
        { \
                perror(m); \
                exit(EXIT_FAILURE); \
        } while(0)

struct packet
{
        int len;
        char buf[1024];
};

ssize_t readn(int fd, void *buf, size_t count)
{
        size_t nleft = count;
        ssize_t nread;
        char *bufp = (char*)buf;

        while (nleft > 0)
        {
                if ((nread = read(fd, bufp, nleft)) < 0)
                {
                        if (errno == EINTR)
                                continue;
                        return -1;
                }
                else if (nread == 0)
                        return count - nleft;

                bufp += nread;
                nleft -= nread;
        }

        return count;
}

ssize_t writen(int fd, const void *buf, size_t count)
{
        size_t nleft = count;
        ssize_t nwritten;
        char *bufp = (char*)buf;

        while (nleft > 0)
        {
            if ((nwritten = write(fd, bufp, nleft)) < 0)
            {
                    if (errno == EINTR)
                            continue;
                    return -1;
            }
            else if (nwritten == 0)
                    continue;

            bufp += nwritten;
            nleft -= nwritten;
        }

        return count;
}

int main(void)
{
	int sock;
	if ((sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
		ERR_EXIT("socket");

	struct sockaddr_in servaddr;
	memset(&servaddr, 0, sizeof(servaddr));
	servaddr.sin_family = AF_INET;
	servaddr.sin_port = htons(8001);
	servaddr.sin_addr.s_addr = inet_addr("127.0.0.1"); 

	if (connect(sock, (struct sockaddr*)&servaddr, sizeof(servaddr)) < 0)
		ERR_EXIT("connect");


	struct packet sendbuf;
	struct packet recvbuf;
	memset(&sendbuf, 0, sizeof(sendbuf));
	memset(&recvbuf, 0, sizeof(recvbuf));
	int n;
	while (fgets(sendbuf.buf, sizeof(sendbuf.buf), stdin) != NULL)
	{
		n = strlen(sendbuf.buf);
		sendbuf.len = htonl(n);	
		writen(sock, &sendbuf, 4+n);


		int ret = readn(sock, &recvbuf.len, 4);
        if (ret == -1)
                ERR_EXIT("read");
        else if (ret < 4)
        {
                printf("client close\n");
                break;
        }
        
        n = ntohl(recvbuf.len);
        ret = readn(sock, recvbuf.buf, n);
        if (ret == -1)
                ERR_EXIT("read");
        else if (ret < n)
        {
                printf("client close\n");
                break;
        }


		fputs(recvbuf.buf, stdout);
		memset(&sendbuf, 0, sizeof(sendbuf));
		memset(&recvbuf, 0, sizeof(recvbuf));
	}

	close(sock);
	
	return 0;
}

相關推薦

linux程序伺服器示例

伺服器端#include <unistd.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/i

一個epoll程序伺服器示例

#include<iostream> #include<stdlib.h> #include<string.h> #include<sys/types.h> #include<arpa/inet.h> #inclu

Linux程序併發伺服器(TCP)

Linux多程序併發伺服器(TCP) 前言:在Linux環境下多程序的應用很多,其中最主要的就是網路/客戶伺服器。多程序伺服器是當客戶有請求時 ,伺服器用一個子程序來處理客戶請求。父程序繼續等待其它客戶的請求。這種方法的優點是當客戶有請求時 ,伺服器能及時處理客戶 ,特別是在客戶伺服

基於TCP協議實現Linux下客戶端與伺服器之間的通訊,實現執行緒、程序伺服器

TCP是TCP/IP協議族中一個比較重要的協議,這是一種可靠、建立連結、面向位元組流的傳輸,工作在傳輸層。和TCP相對的不可靠、無連結、面向資料報的協議UDP,瞭解UDP客戶端與伺服器之間通訊請戳UDP協議實現的伺服器與客戶端通訊 TCP協議建立連線 首

Python中的程序示例

#!/usr/bin/python # -*- coding:utf-8 -*- import requests import json import time from multiprocessing import Pool def func(name): print('

linux 程序程式設計詳解

1.建立程序fork() 1.1標頭檔案 #include<unistd.h> #include<sys/types.h> 1.2函式原型 pid_t fork( void); pid_t 是一個巨集定義,其實質是int 被定義在#i

Linux程序執行緒的優缺點

教科書上最經典的一句話是“程序是作業系統分配的最小單位,執行緒是CPU排程的最小單位”。 多執行緒的優點: 1)它是一種非常”節儉”的多工操作方式。在Linux系統下,啟動一個新的程序必須分配給它獨立的地址空間,建立眾多的資料表來維護它的程式碼段、堆疊段和資料段,這是一種”昂貴”

linux程序執行緒

轉載自CodeUniverse的部落格 程序:可執行程式是儲存在磁碟裝置上的由程式碼和資料按某種格式組織的靜態實體,而程序是可被排程的程式碼的動態執行。 在Linux系統中,每個程序都有各自的生命週期。在一個程序的生命週期中,都有各自的執行環境以及所需的資源,這些資訊都記錄在各自的程序控制塊中,以便系統對

node程序伺服器

node提供了四種方法來建立子程序,分別是child_process.exec(),child_process.execFile(), child_process.fork(),child_process.spawn()。他們都返回子程序物件。exec:啟動一個子程序執行命令,並且有一個回撥函式獲知子程序的狀

程序伺服器中,epoll的建立應該在建立子程序之後

#include <iostream>#include <sys/socket.h>#include <sys/epoll.h>#include <netinet/in.h>#include <arpa/inet.h>#include <fcn

Linux程序和執行緒同步的幾種方式

   引用:http://community.csdn.net/Expert/TopicView3.asp?id=4374496 linux下程序間通訊的幾種主要手段簡介:    1. 管道(Pipe)及有名管道(named pipe):管道可用於具有親緣關係程序間的通訊,有名管道克服了管道沒有名字的

程序伺服器(python 版)

多程序伺服器 1. 多程序伺服器from socket import * from multiprocessing import * from time import sleep # 處理客戶端的請

網路程式設計 筆記(六) 程序伺服器

程序 - 程序(Process):“佔用記憶體空間的正在執行的程式” - 程序ID :作業系統給程序分配的id,其值大於2,1要分配給作業系統啟動後的首個程序 -linux檢視程序的命令:ps au ;引數a和u列出所有程序的詳細資訊 通過fo

Linux伺服器間SSH免密碼登入配置

SSH實現各個伺服器間的檔案相互備份,如執行scp命令,可以實現免密碼登入,從而可以使用SHELL指令碼實現一些自動化的處理。 假如A機要免密碼登入B機,具體方法如下: 1、在A機執行:"ssh-keygen -t rsa" 命令,建立公鑰資訊 #ssh-keygen

linux 程序

Linux下的多程序程式設計初步 2. 多程序程式設計 什麼是一個程序?程序這個概念是針對系統而不是針對使用者的,對使用者來說,他面對的概念是程式。當用戶敲入命令執行一個程式的時候,對系統而言,它將啟動一個程序。但和程式不同的是,在這個程序中,系統可能

Linux程序通訊】訊號

注意區分訊號與訊號量之間的區別。 一、什麼是訊號 用過Windows的我們都知道,當我們無法正常結束一個程式時,可以用工作管理員強制結束這個程序,但這其實是怎麼實現的呢?同樣的功能在Linux上是通過生成訊號和捕獲訊號來實現的,執行中的程序捕獲到這個訊號然後作出一

程序伺服器

前面的話  伺服器按處理方式可以分為迭代伺服器和併發伺服器兩類。平常用C寫的簡單Socket客戶端伺服器通訊,伺服器每次只能處理一個客戶的請求,它實現簡單但效率很低,通常這種伺服器被稱為迭代伺服器。 然而在實際應用中,不可能讓一個伺服器長時間地為一個客戶服務,而需要其具有同時

如何實現Linux伺服器間的檔案雙向同步

Linux系統間檔案雙向同步搭建Unison版  一、Unison簡介  Unison是Windows、Linux以及其他Unix平臺下都可以使用的檔案同步工具,它能使兩個資料夾(本地或網路上的)保持內容的一致。Unison擁有與其它一些同步工具或檔案系統的相同的特性,但也有自身的特點:  1.跨平臺

select伺服器端的程式碼以及select的優缺點與執行緒程序伺服器的比較

 22     struct sockaddr_in local;  23     local.sin_family=AF_INET;  24     local.sin_port=htons(port);  25     local.sin_addr.s_addr=inet_addr(ip);  26  

基於訊息佇列的程序伺服器

目錄一、思路二、實現2. 修改2.1 思路2.2 程式碼 一、思路 1)server程序接收時, 指定msgtyp為0, 從隊首不斷接收訊息; 2)server程序傳送時, 將mtype指定為接收到的client程序的pid; 3)client程序傳送的時候