国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

計(jì)算機(jī)網(wǎng)絡(luò)編程 | 多路I/O轉(zhuǎn)接服務(wù)器

這篇具有很好參考價(jià)值的文章主要介紹了計(jì)算機(jī)網(wǎng)絡(luò)編程 | 多路I/O轉(zhuǎn)接服務(wù)器。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問。

計(jì)算機(jī)網(wǎng)絡(luò)編程 | 多路I/O轉(zhuǎn)接服務(wù)器,網(wǎng)絡(luò)編程,服務(wù)器,IO多路轉(zhuǎn)接,計(jì)算機(jī)網(wǎng)絡(luò),tcp/ip,linux,網(wǎng)絡(luò)編程,select,原力計(jì)劃

歡迎關(guān)注博主 Mindtechnist 或加入【Linux C/C++/Python社區(qū)】一起學(xué)習(xí)和分享Linux、C、C++、Python、Matlab,機(jī)器人運(yùn)動(dòng)控制、多機(jī)器人協(xié)作,智能優(yōu)化算法,濾波估計(jì)、多傳感器信息融合,機(jī)器學(xué)習(xí),人工智能等相關(guān)領(lǐng)域的知識(shí)和技術(shù)。



專欄:《網(wǎng)絡(luò)編程》


多路IO轉(zhuǎn)接服務(wù)器也叫做多任務(wù)IO服務(wù)器。該類服務(wù)器實(shí)現(xiàn)的主旨思想是,不再由應(yīng)用程序自己監(jiān)視客戶端連接,取而代之由內(nèi)核替應(yīng)用程序監(jiān)視文件。
主要使用的方法有三種,下面一一介紹并給出代碼實(shí)現(xiàn)。

select

  • select能監(jiān)聽的文件描述符個(gè)數(shù)受限于FD_SETSIZE,一般為1024,單純改變進(jìn)程打開的文件描述符個(gè)數(shù)并不能改變select監(jiān)聽文件個(gè)數(shù)。
  • 解決1024以下客戶端時(shí)使用select是很合適的,但如果鏈接客戶端過多,select采用的是輪詢模型,會(huì)大大降低服務(wù)器響應(yīng)效率,不應(yīng)在select上投入更多精力。
#include <sys/select.h>
/* According to earlier standards */
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
int select(int nfds, fd_set *readfds, fd_set *writefds,
			fd_set *exceptfds, struct timeval *timeout);

nfds: 監(jiān)控的文件描述符集里最大文件描述符加1,因?yàn)榇藚?shù)會(huì)告訴內(nèi)核檢測(cè)前多少個(gè)文件描述符的狀態(tài)
readfds: 監(jiān)控有讀數(shù)據(jù)到達(dá)文件描述符集合,傳入傳出參數(shù)
writefds: 監(jiān)控寫數(shù)據(jù)到達(dá)文件描述符集合,傳入傳出參數(shù)
exceptfds: 監(jiān)控異常發(fā)生達(dá)文件描述符集合,如帶外數(shù)據(jù)到達(dá)異常,傳入傳出參數(shù)
timeout: 定時(shí)阻塞監(jiān)控時(shí)間,3種情況
①NULL,永遠(yuǎn)等下去
②設(shè)置timeval,等待固定時(shí)間
③設(shè)置timeval里時(shí)間均為0,檢查描述字后立即返回,輪詢

	struct timeval {
		long tv_sec; /* seconds */
		long tv_usec; /* microseconds */
	};
	void FD_CLR(int fd, fd_set *set); 	//把文件描述符集合里fd清0
	int FD_ISSET(int fd, fd_set *set); 	//測(cè)試文件描述符集合里fd是否置1
	void FD_SET(int fd, fd_set *set); 	//把文件描述符集合里fd位置1
	void FD_ZERO(fd_set *set); 			//把文件描述符集合里所有位清0

server實(shí)現(xiàn)

/* server.c */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include "wrap.h"

#define MAXLINE 80
#define SERV_PORT 6666

int main(int argc, char *argv[])
{
	int i, maxi, maxfd, listenfd, connfd, sockfd;
	int nready, client[FD_SETSIZE]; 	/* FD_SETSIZE 默認(rèn)為 1024 */
	ssize_t n;
	fd_set rset, allset;
	char buf[MAXLINE];
	char str[INET_ADDRSTRLEN]; 			/* #define INET_ADDRSTRLEN 16 */
	socklen_t cliaddr_len;
	struct sockaddr_in cliaddr, servaddr;

	listenfd = Socket(AF_INET, SOCK_STREAM, 0);

bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
servaddr.sin_port = htons(SERV_PORT);

Bind(listenfd, (struct sockaddr *)&servaddr, sizeof(servaddr));

Listen(listenfd, 20); 		/* 默認(rèn)最大128 */

maxfd = listenfd; 			/* 初始化 */
maxi = -1;					/* client[]的下標(biāo) */

for (i = 0; i < FD_SETSIZE; i++)
	client[i] = -1; 		/* 用-1初始化client[] */

FD_ZERO(&allset);
FD_SET(listenfd, &allset); /* 構(gòu)造select監(jiān)控文件描述符集 */

for ( ; ; ) {
	rset = allset; 			/* 每次循環(huán)時(shí)都從新設(shè)置select監(jiān)控信號(hào)集 */
	nready = select(maxfd+1, &rset, NULL, NULL, NULL);

	if (nready < 0)
		perr_exit("select error");
	if (FD_ISSET(listenfd, &rset)) { /* new client connection */
		cliaddr_len = sizeof(cliaddr);
		connfd = Accept(listenfd, (struct sockaddr *)&cliaddr, &cliaddr_len);
		printf("received from %s at PORT %d\n",
				inet_ntop(AF_INET, &cliaddr.sin_addr, str, sizeof(str)),
				ntohs(cliaddr.sin_port));
		for (i = 0; i < FD_SETSIZE; i++) {
			if (client[i] < 0) {
				client[i] = connfd; /* 保存accept返回的文件描述符到client[]里 */
				break;
			}
		}
		/* 達(dá)到select能監(jiān)控的文件個(gè)數(shù)上限 1024 */
		if (i == FD_SETSIZE) {
			fputs("too many clients\n", stderr);
			exit(1);
		}

		FD_SET(connfd, &allset); 	/* 添加一個(gè)新的文件描述符到監(jiān)控信號(hào)集里 */
		if (connfd > maxfd)
			maxfd = connfd; 		/* select第一個(gè)參數(shù)需要 */
		if (i > maxi)
			maxi = i; 				/* 更新client[]最大下標(biāo)值 */

		if (--nready == 0)
			continue; 				/* 如果沒有更多的就緒文件描述符繼續(xù)回到上面select阻塞監(jiān)聽,
										負(fù)責(zé)處理未處理完的就緒文件描述符 */
		}
		for (i = 0; i <= maxi; i++) { 	/* 檢測(cè)哪個(gè)clients 有數(shù)據(jù)就緒 */
			if ( (sockfd = client[i]) < 0)
				continue;
			if (FD_ISSET(sockfd, &rset)) {
				if ( (n = Read(sockfd, buf, MAXLINE)) == 0) {
					Close(sockfd);		/* 當(dāng)client關(guān)閉鏈接時(shí),服務(wù)器端也關(guān)閉對(duì)應(yīng)鏈接 */
					FD_CLR(sockfd, &allset); /* 解除select監(jiān)控此文件描述符 */
					client[i] = -1;
				} else {
					int j;
					for (j = 0; j < n; j++)
						buf[j] = toupper(buf[j]);
					Write(sockfd, buf, n);
				}
				if (--nready == 0)
					break;
			}
		}
	}
	close(listenfd);
	return 0;
}

client實(shí)現(xiàn)

/* client.c */
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <netinet/in.h>
#include "wrap.h"

#define MAXLINE 80
#define SERV_PORT 6666

int main(int argc, char *argv[])
{
	struct sockaddr_in servaddr;
	char buf[MAXLINE];
	int sockfd, n;

	sockfd = Socket(AF_INET, SOCK_STREAM, 0);

	bzero(&servaddr, sizeof(servaddr));
	servaddr.sin_family = AF_INET;
	inet_pton(AF_INET, "127.0.0.1", &servaddr.sin_addr);
	servaddr.sin_port = htons(SERV_PORT);

	Connect(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr));

	while (fgets(buf, MAXLINE, stdin) != NULL) {
		Write(sockfd, buf, strlen(buf));
		n = Read(sockfd, buf, MAXLINE);
		if (n == 0)
			printf("the other side has been closed.\n");
		else
			Write(STDOUT_FILENO, buf, n);
	}
	Close(sockfd);
	return 0;
}

pselect
pselect原型如下。此模型應(yīng)用較少。

#include <sys/select.h>
int pselect(int nfds, fd_set *readfds, fd_set *writefds,
			fd_set *exceptfds, const struct timespec *timeout,
			const sigset_t *sigmask);
	struct timespec {
		long tv_sec; /* seconds */
		long tv_nsec; /* nanoseconds */
	};

用sigmask替代當(dāng)前進(jìn)程的阻塞信號(hào)集,調(diào)用返回后還原原有阻塞信號(hào)集。

poll

#include <poll.h>
int poll(struct pollfd *fds, nfds_t nfds, int timeout);
	struct pollfd {
		int fd; /* 文件描述符 */
		short events; /* 監(jiān)控的事件 */
		short revents; /* 監(jiān)控事件中滿足條件返回的事件 */
	};

POLLIN 普通或帶外優(yōu)先數(shù)據(jù)可讀,即POLLRDNORM | POLLRDBAND
POLLRDNORM 數(shù)據(jù)可讀
POLLRDBAND 優(yōu)先級(jí)帶數(shù)據(jù)可讀
POLLPRI 高優(yōu)先級(jí)可讀數(shù)據(jù)
POLLOUT 普通或帶外數(shù)據(jù)可寫
POLLWRNORM 數(shù)據(jù)可寫
POLLWRBAND 優(yōu)先級(jí)帶數(shù)據(jù)可寫
POLLERR 發(fā)生錯(cuò)誤
POLLHUP 發(fā)生掛起
POLLNVAL 描述字不是一個(gè)打開的文件

nfds 監(jiān)控?cái)?shù)組中有多少文件描述符需要被監(jiān)控

timeout 毫秒級(jí)等待
-1:阻塞等,#define INFTIM -1 , Linux中沒有定義此宏。
0:立即返回,不阻塞進(jìn)程。
> 0:等待指定毫秒數(shù),如當(dāng)前系統(tǒng)時(shí)間精度不夠毫秒,向上取值。

如果不再監(jiān)控某個(gè)文件描述符時(shí),可以把pollfd中,fd設(shè)置為-1,poll不再監(jiān)控此pollfd,下次返回時(shí),把revents設(shè)置為0。

server實(shí)現(xiàn)

/* server.c */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <poll.h>
#include <errno.h>
#include "wrap.h"

#define MAXLINE 80
#define SERV_PORT 6666
#define OPEN_MAX 1024

int main(int argc, char *argv[])
{
	int i, j, maxi, listenfd, connfd, sockfd;
	int nready;
	ssize_t n;
	char buf[MAXLINE], str[INET_ADDRSTRLEN];
	socklen_t clilen;
	struct pollfd client[OPEN_MAX];
	struct sockaddr_in cliaddr, servaddr;

	listenfd = Socket(AF_INET, SOCK_STREAM, 0);

	bzero(&servaddr, sizeof(servaddr));
	servaddr.sin_family = AF_INET;
	servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
	servaddr.sin_port = htons(SERV_PORT);

	Bind(listenfd, (struct sockaddr *)&servaddr, sizeof(servaddr));

	Listen(listenfd, 20);

	client[0].fd = listenfd;
	client[0].events = POLLRDNORM; 					/* listenfd監(jiān)聽普通讀事件 */

	for (i = 1; i < OPEN_MAX; i++)
		client[i].fd = -1; 							/* 用-1初始化client[]里剩下元素 */
	maxi = 0; 										/* client[]數(shù)組有效元素中最大元素下標(biāo) */

	for ( ; ; ) {
		nready = poll(client, maxi+1, -1); 			/* 阻塞 */
		if (client[0].revents & POLLRDNORM) { 		/* 有客戶端鏈接請(qǐng)求 */
			clilen = sizeof(cliaddr);
			connfd = Accept(listenfd, (struct sockaddr *)&cliaddr, &clilen);
			printf("received from %s at PORT %d\n",
					inet_ntop(AF_INET, &cliaddr.sin_addr, str, sizeof(str)),
					ntohs(cliaddr.sin_port));
			for (i = 1; i < OPEN_MAX; i++) {
				if (client[i].fd < 0) {
					client[i].fd = connfd; 	/* 找到client[]中空閑的位置,存放accept返回的connfd */
					break;
				}
			}

			if (i == OPEN_MAX)
				perr_exit("too many clients");

			client[i].events = POLLRDNORM; 		/* 設(shè)置剛剛返回的connfd,監(jiān)控讀事件 */
			if (i > maxi)
				maxi = i; 						/* 更新client[]中最大元素下標(biāo) */
			if (--nready <= 0)
				continue; 						/* 沒有更多就緒事件時(shí),繼續(xù)回到poll阻塞 */
		}
		for (i = 1; i <= maxi; i++) { 			/* 檢測(cè)client[] */
			if ((sockfd = client[i].fd) < 0)
				continue;
			if (client[i].revents & (POLLRDNORM | POLLERR)) {
				if ((n = Read(sockfd, buf, MAXLINE)) < 0) {
					if (errno == ECONNRESET) { /* 當(dāng)收到 RST標(biāo)志時(shí) */
						/* connection reset by client */
						printf("client[%d] aborted connection\n", i);
						Close(sockfd);
						client[i].fd = -1;
					} else {
						perr_exit("read error");
					}
				} else if (n == 0) {
					/* connection closed by client */
					printf("client[%d] closed connection\n", i);
					Close(sockfd);
					client[i].fd = -1;
				} else {
					for (j = 0; j < n; j++)
						buf[j] = toupper(buf[j]);
						Writen(sockfd, buf, n);
				}
				if (--nready <= 0)
					break; 				/* no more readable descriptors */
			}
		}
	}
	return 0;
}

client實(shí)現(xiàn)

/* client.c */
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <netinet/in.h>
#include "wrap.h"

#define MAXLINE 80
#define SERV_PORT 6666

int main(int argc, char *argv[])
{
	struct sockaddr_in servaddr;
	char buf[MAXLINE];
	int sockfd, n;

	sockfd = Socket(AF_INET, SOCK_STREAM, 0);

	bzero(&servaddr, sizeof(servaddr));
	servaddr.sin_family = AF_INET;
	inet_pton(AF_INET, "127.0.0.1", &servaddr.sin_addr);
	servaddr.sin_port = htons(SERV_PORT);

	Connect(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr));

	while (fgets(buf, MAXLINE, stdin) != NULL) {
		Write(sockfd, buf, strlen(buf));
		n = Read(sockfd, buf, MAXLINE);
		if (n == 0)
			printf("the other side has been closed.\n");
		else
			Write(STDOUT_FILENO, buf, n);
	}
	Close(sockfd);
	return 0;
}

ppoll
GNU定義了ppoll(非POSIX標(biāo)準(zhǔn)),可以支持設(shè)置信號(hào)屏蔽字。

#define _GNU_SOURCE /* See feature_test_macros(7) */
#include <poll.h>
int ppoll(struct pollfd *fds, nfds_t nfds,
		   const struct timespec *timeout_ts, const sigset_t *sigmask);

epoll

epoll是Linux下多路復(fù)用IO接口select/poll的增強(qiáng)版本,它能顯著提高程序在大量并發(fā)連接中只有少量活躍的情況下的系統(tǒng)CPU利用率,因?yàn)樗鼤?huì)復(fù)用文件描述符集合來(lái)傳遞結(jié)果而不用迫使開發(fā)者每次等待事件之前都必須重新準(zhǔn)備要被偵聽的文件描述符集合,另一點(diǎn)原因就是獲取事件的時(shí)候,它無(wú)須遍歷整個(gè)被偵聽的描述符集,只要遍歷那些被內(nèi)核IO事件異步喚醒而加入Ready隊(duì)列的描述符集合就行了。
目前epell是linux大規(guī)模并發(fā)網(wǎng)絡(luò)程序中的熱門首選模型。
epoll除了提供select/poll那種IO事件的電平觸發(fā)(Level Triggered)外,還提供了邊沿觸發(fā)(Edge Triggered),這就使得用戶空間程序有可能緩存IO狀態(tài),減少epoll_wait/epoll_pwait的調(diào)用,提高應(yīng)用程序效率。
可以使用cat命令查看一個(gè)進(jìn)程可以打開的socket描述符上限。

cat /proc/sys/fs/file-max

如有需要,可以通過修改配置文件的方式修改該上限值。

sudo vi /etc/security/limits.conf

在文件尾部寫入以下配置,soft軟限制,hard硬限制。

* soft nofile 65536
* hard nofile 100000

基礎(chǔ)API
創(chuàng)建一個(gè)epoll句柄,參數(shù)size用來(lái)告訴內(nèi)核監(jiān)聽的文件描述符的個(gè)數(shù),跟內(nèi)存大小有關(guān)。

#include <sys/epoll.h>
int epoll_create(int size)		//size:監(jiān)聽數(shù)目

控制某個(gè)epoll監(jiān)控的文件描述符上的事件:注冊(cè)、修改、刪除。

#include <sys/epoll.h>
int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event)

epfd: 為epoll_creat的句柄。
op: 表示動(dòng)作,用3個(gè)宏來(lái)表示:
-EPOLL_CTL_ADD (注冊(cè)新的fd到epfd),
-EPOLL_CTL_MOD (修改已經(jīng)注冊(cè)的fd的監(jiān)聽事件),
-EPOLL_CTL_DEL (從epfd刪除一個(gè)fd);
event: 告訴內(nèi)核需要監(jiān)聽的事件。

struct epoll_event {
	__uint32_t events; /* Epoll events */
	epoll_data_t data; /* User data variable */
};
typedef union epoll_data {
	void *ptr;
	int fd;
	uint32_t u32;
	uint64_t u64;
} epoll_data_t;

EPOLLIN : 表示對(duì)應(yīng)的文件描述符可以讀(包括對(duì)端SOCKET正常關(guān)閉)。
EPOLLOUT: 表示對(duì)應(yīng)的文件描述符可以寫。
EPOLLPRI: 表示對(duì)應(yīng)的文件描述符有緊急的數(shù)據(jù)可讀(這里應(yīng)該表示有帶外數(shù)據(jù)到來(lái))。
EPOLLERR: 表示對(duì)應(yīng)的文件描述符發(fā)生錯(cuò)誤。
EPOLLHUP: 表示對(duì)應(yīng)的文件描述符被掛斷。
EPOLLET: 將EPOLL設(shè)為邊緣觸發(fā)(Edge Triggered)模式,這是相對(duì)于水平觸發(fā)(Level Triggered)而言的。
EPOLLONESHOT:只監(jiān)聽一次事件,當(dāng)監(jiān)聽完這次事件之后,如果還需要繼續(xù)監(jiān)聽這個(gè)socket的話,需要再次把這個(gè)socket加入到EPOLL隊(duì)列里。

等待所監(jiān)控文件描述符上有事件的產(chǎn)生,類似于select()調(diào)用。

#include <sys/epoll.h>
	int epoll_wait(int epfd, struct epoll_event *events, int maxevents, int timeout);

events: 用來(lái)存內(nèi)核得到事件的集合。
maxevents: 告之內(nèi)核這個(gè)events有多大,這個(gè)maxevents的值不能大于創(chuàng)建epoll_create()時(shí)的size。
timeout: 是超時(shí)時(shí)間
-1: 阻塞
0: 立即返回,非阻塞
>0: 指定毫秒
返回值: 成功返回有多少文件描述符就緒,時(shí)間到時(shí)返回0,出錯(cuò)返回-1

server

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/epoll.h>
#include <errno.h>
#include "wrap.h"

#define MAXLINE 80
#define SERV_PORT 6666
#define OPEN_MAX 1024

int main(int argc, char *argv[])
{
	int i, j, maxi, listenfd, connfd, sockfd;
	int nready, efd, res;
	ssize_t n;
	char buf[MAXLINE], str[INET_ADDRSTRLEN];
	socklen_t clilen;
	int client[OPEN_MAX];
	struct sockaddr_in cliaddr, servaddr;
	struct epoll_event tep, ep[OPEN_MAX];

	listenfd = Socket(AF_INET, SOCK_STREAM, 0);

	bzero(&servaddr, sizeof(servaddr));
	servaddr.sin_family = AF_INET;
	servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
	servaddr.sin_port = htons(SERV_PORT);

	Bind(listenfd, (struct sockaddr *) &servaddr, sizeof(servaddr));

	Listen(listenfd, 20);

	for (i = 0; i < OPEN_MAX; i++)
		client[i] = -1;
	maxi = -1;

	efd = epoll_create(OPEN_MAX);
	if (efd == -1)
		perr_exit("epoll_create");

	tep.events = EPOLLIN; tep.data.fd = listenfd;

	res = epoll_ctl(efd, EPOLL_CTL_ADD, listenfd, &tep);
	if (res == -1)
		perr_exit("epoll_ctl");

	while (1) {
		nready = epoll_wait(efd, ep, OPEN_MAX, -1); /* 阻塞監(jiān)聽 */
		if (nready == -1)
			perr_exit("epoll_wait");

		for (i = 0; i < nready; i++) {
			if (!(ep[i].events & EPOLLIN))
				continue;
			if (ep[i].data.fd == listenfd) {
				clilen = sizeof(cliaddr);
				connfd = Accept(listenfd, (struct sockaddr *)&cliaddr, &clilen);
				printf("received from %s at PORT %d\n", 
						inet_ntop(AF_INET, &cliaddr.sin_addr, str, sizeof(str)), 
						ntohs(cliaddr.sin_port));
				for (j = 0; j < OPEN_MAX; j++) {
					if (client[j] < 0) {
						client[j] = connfd; /* save descriptor */
						break;
					}
				}

				if (j == OPEN_MAX)
					perr_exit("too many clients");
				if (j > maxi)
					maxi = j; 		/* max index in client[] array */

				tep.events = EPOLLIN; 
				tep.data.fd = connfd;
				res = epoll_ctl(efd, EPOLL_CTL_ADD, connfd, &tep);
				if (res == -1)
					perr_exit("epoll_ctl");
			} else {
				sockfd = ep[i].data.fd;
				n = Read(sockfd, buf, MAXLINE);
				if (n == 0) {
					for (j = 0; j <= maxi; j++) {
						if (client[j] == sockfd) {
							client[j] = -1;
							break;
						}
					}
					res = epoll_ctl(efd, EPOLL_CTL_DEL, sockfd, NULL);
					if (res == -1)
						perr_exit("epoll_ctl");

					Close(sockfd);
					printf("client[%d] closed connection\n", j);
				} else {
					for (j = 0; j < n; j++)
						buf[j] = toupper(buf[j]);
					Writen(sockfd, buf, n);
				}
			}
		}
	}
	close(listenfd);
	close(efd);
	return 0;
}

client

/* client.c */
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <netinet/in.h>
#include "wrap.h"

#define MAXLINE 80
#define SERV_PORT 6666

int main(int argc, char *argv[])
{
	struct sockaddr_in servaddr;
	char buf[MAXLINE];
	int sockfd, n;

	sockfd = Socket(AF_INET, SOCK_STREAM, 0);

	bzero(&servaddr, sizeof(servaddr));
	servaddr.sin_family = AF_INET;
	inet_pton(AF_INET, "127.0.0.1", &servaddr.sin_addr);
	servaddr.sin_port = htons(SERV_PORT);

	Connect(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr));

	while (fgets(buf, MAXLINE, stdin) != NULL) {
		Write(sockfd, buf, strlen(buf));
		n = Read(sockfd, buf, MAXLINE);
		if (n == 0)
			printf("the other side has been closed.\n");
		else
			Write(STDOUT_FILENO, buf, n);
	}

	Close(sockfd);
	return 0;
}

計(jì)算機(jī)網(wǎng)絡(luò)編程 | 多路I/O轉(zhuǎn)接服務(wù)器,網(wǎng)絡(luò)編程,服務(wù)器,IO多路轉(zhuǎn)接,計(jì)算機(jī)網(wǎng)絡(luò),tcp/ip,linux,網(wǎng)絡(luò)編程,select,原力計(jì)劃
計(jì)算機(jī)網(wǎng)絡(luò)編程 | 多路I/O轉(zhuǎn)接服務(wù)器,網(wǎng)絡(luò)編程,服務(wù)器,IO多路轉(zhuǎn)接,計(jì)算機(jī)網(wǎng)絡(luò),tcp/ip,linux,網(wǎng)絡(luò)編程,select,原力計(jì)劃文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-520912.html


到了這里,關(guān)于計(jì)算機(jī)網(wǎng)絡(luò)編程 | 多路I/O轉(zhuǎn)接服務(wù)器的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來(lái)自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場(chǎng)。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請(qǐng)注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請(qǐng)點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請(qǐng)作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包