日本搞逼视频_黄色一级片免费在线观看_色99久久_性明星video另类hd_欧美77_综合在线视频

國(guó)內(nèi)最全I(xiàn)T社區(qū)平臺(tái) 聯(lián)系我們 | 收藏本站
阿里云優(yōu)惠2
您當(dāng)前位置:首頁(yè) > 互聯(lián)網(wǎng) > Socket編程實(shí)踐(7) --TCP服務(wù)器常見(jiàn)問(wèn)題(2)

Socket編程實(shí)踐(7) --TCP服務(wù)器常見(jiàn)問(wèn)題(2)

來(lái)源:程序員人生   發(fā)布時(shí)間:2014-12-19 08:21:43 閱讀次數(shù):3221次

包尾加 編程實(shí)踐

SYNOPSIS #include <sys/types.h> #include <sys/socket.h> ssize_t recv(int sockfd, void *buf, size_t len, int flags);

與read相比,只能用于套接字文件描寫(xiě)符,而且多了1個(gè)flags


Flags經(jīng)常使用取值:

MSG_OOB(緊急指針,帶外數(shù)據(jù))

 This flag requests receipt of out-of-band data that would not be received  in the normal data stream.  Some protocols place expedited data at the head of the normal data queue, and  thus  this flag cannot be used with such protocols.

 

MSG_PEEK(可以讀數(shù)據(jù),不從緩存區(qū)中讀走,利用此特點(diǎn)可以方便的實(shí)現(xiàn)按行讀取數(shù)據(jù);1個(gè)1個(gè)字符的讀,方法不好;屢次調(diào)用系統(tǒng)調(diào)用read方法)

 This  flag  causes the receive operation to return data from the beginning of the receive queue without removing that  data  from the queue.  Thus, a subsequent receive call will return the same data.

 

1.原客戶端代碼分析

  .... //從鍵盤(pán)輸入數(shù)據(jù):調(diào)用fgets函數(shù),行尾的/n是默許自帶的,請(qǐng)參看下圖gdb調(diào)試的截圖 while (fgets(sendBuf.m_text,sizeof(sendBuf.m_text),stdin) != NULL) { //保存的是真實(shí)報(bào)文的長(zhǎng)度 sendBuf.m_length = strlen(sendBuf.m_text); //向server發(fā)送數(shù)據(jù)....+4的緣由:需要添加報(bào)首的4個(gè)字節(jié)報(bào)頭的長(zhǎng)度 if (writen(sockfd,&sendBuf,sendBuf.m_length+4) == ⑴) { err_exit("write socket error"); } .....

2.readline函數(shù)實(shí)現(xiàn)及解析

//只是查看1下網(wǎng)絡(luò)中的數(shù)據(jù),其實(shí)不是將之真正取走:MSG_PEEK ssize_t recv_peek(int fd, void *buf, size_t count) { int nRead = 0; //如果讀取網(wǎng)絡(luò)數(shù)據(jù)出錯(cuò),則繼續(xù)讀取 while ((nRead = recv(fd,buf,count,MSG_PEEK)) == ⑴); return nRead; } ssize_t readline(int fd, void *buf, size_t maxline) { char *pBuf = (char *)buf; int nLeft = maxline; while (true) { //查看緩沖區(qū)中的數(shù)據(jù),其實(shí)不真正取走 int nTestRead = recv_peek(fd,pBuf,nLeft); //檢測(cè)這次讀來(lái)的數(shù)據(jù)中是不是包括' '; //如果有,則將之全部讀取出來(lái) for (int i = 0; i < nTestRead; ++i) { if (pBuf[i] == ' ') { //真實(shí)的從緩沖區(qū)中將數(shù)據(jù)取走 if (readn(fd,pBuf,i+1) != i+1) { err_exit("readn error"); } else { return i + 1; } } } //如果這次讀的緩沖區(qū)中沒(méi)有' ' //如果讀超了:讀道德數(shù)目大于1行最大數(shù),則做異常處理 if (nTestRead > nLeft) { exit(EXIT_FAILURE); } nLeft -= nTestRead; //若緩沖區(qū)沒(méi)有' ',則將剩余的數(shù)據(jù)讀走 if (readn(fd,pBuf,nTestRead) != nTestRead) { exit(EXIT_FAILURE); } pBuf += nTestRead; } return ⑴; }

3.server完全代碼及解析

#include "commen.h" //echo 服務(wù)器readline版 int main() { int sockfd = socket(AF_INET,SOCK_STREAM,0); if (sockfd == ⑴) { err_exit("socket error"); } //添加地址復(fù)用 int optval = 1; if (setsockopt(sockfd,SOL_SOCKET,SO_REUSEADDR,&optval,sizeof(optval)) == ⑴) { err_exit("setsockopt SO_REUSEADDR error"); } //綁定 struct sockaddr_in serverAddr; serverAddr.sin_family = AF_INET; serverAddr.sin_port = htons(8002); serverAddr.sin_addr.s_addr = INADDR_ANY; //綁定本機(jī)的任意1個(gè)IP地址 if (bind(sockfd,(struct sockaddr *)&serverAddr,sizeof(serverAddr)) == ⑴) { err_exit("bind error"); } //啟動(dòng)監(jiān)聽(tīng)套接字 if (listen(sockfd,SOMAXCONN) == ⑴) { err_exit("listen error"); } struct sockaddr_in peerAddr; socklen_t peerLen = sizeof(peerAddr); while (true) { //接受鏈接 int peerSockfd = accept(sockfd, (struct sockaddr *)&peerAddr,&peerLen); if (peerSockfd == ⑴) { err_exit("accept error"); } //打印客戶信息 cout << "Client:" << endl; cout << " sin_port: " << ntohs(peerAddr.sin_port) << endl; cout << " sin_addr: " << inet_ntoa(peerAddr.sin_addr) << endl; cout << " socket: " << peerSockfd << endl; //每有1個(gè)客戶端連接進(jìn)來(lái),就fork1個(gè)子進(jìn)程, //相應(yīng)的業(yè)務(wù)處理由子進(jìn)程完成,父進(jìn)程繼續(xù)監(jiān)聽(tīng) pid_t pid = fork(); if (pid == ⑴) { close(sockfd); close(peerSockfd); err_exit("fork error"); } else if (pid == 0) //子進(jìn)程,處理業(yè)務(wù) { close(sockfd); //子進(jìn)程關(guān)閉監(jiān)聽(tīng)套接字,由于子進(jìn)程不負(fù)責(zé)監(jiān)聽(tīng)?wèi){務(wù) char recvBuf[BUFSIZ]; ssize_t readCount = 0; while (true) { memset(recvBuf,0,sizeof(recvBuf)); //讀取1行數(shù)據(jù)(會(huì)根據(jù)數(shù)據(jù)流中的 而終止讀取) if ((readCount = readline(peerSockfd,recvBuf,sizeof(recvBuf))) == ⑴) { err_exit("readn error"); } else if (readCount == 0) { peerClosePrint("client connect closed"); } //將整體報(bào)文回寫(xiě)回客戶端 if (writen(peerSockfd,recvBuf,strlen(recvBuf)) == ⑴) { err_exit("writen error"); } recvBuf[readCount] = 0; //寫(xiě)至終端 fputs(recvBuf,stdout); } } else if (pid > 0) //父進(jìn)程 { close(peerSockfd); } } close(sockfd); return 0; }

4.新版client完全代碼實(shí)現(xiàn)及解析

#include "commen.h" int main() { int sockfd = socket(AF_INET,SOCK_STREAM,0); if (sockfd == ⑴) { err_exit("socket error"); } //填寫(xiě)好服務(wù)器地址及其端口號(hào) struct sockaddr_in serverAddr; serverAddr.sin_family = AF_INET; serverAddr.sin_port = htons(8002); serverAddr.sin_addr.s_addr = inet_addr("127.0.0.1"); if (connect(sockfd,(struct sockaddr *)&serverAddr,sizeof(serverAddr)) == ⑴) { err_exit("connect error"); } int readCount = 0; char sendBuf[BUFSIZ]; char recvBuf[BUFSIZ]; //從鍵盤(pán)輸入數(shù)據(jù):調(diào)用fgets函數(shù),行尾的/n是默許自帶的,請(qǐng)參看下圖gdb調(diào)試的截圖 while (fgets(sendBuf,sizeof(sendBuf),stdin) != NULL) { //向server發(fā)送數(shù)據(jù)(會(huì)自動(dòng)附帶 ) if (writen(sockfd,sendBuf,strlen(sendBuf)) == ⑴) { err_exit("write socket error"); } //從server端接收1行數(shù)據(jù) if ((readCount = readline(sockfd,recvBuf,sizeof(recvBuf))) == ⑴) { err_exit("read socket error"); } else if (readCount == 0) { peerClosePrint("client connect closed"); } recvBuf[readCount] = 0; //將其回寫(xiě)到終端 fputs(recvBuf,stdout); memset(sendBuf,0,sizeof(sendBuf)); memset(recvBuf,0,sizeof(recvBuf)); } close(sockfd); return 0; }

1-commen.h代碼及解析

#ifndef COMMEN_H_INCLUDED #define COMMEN_H_INCLUDED #include <unistd.h> #include <signal.h> #include <errno.h> #include <fcntl.h> #include <sys/types.h> #include <sys/wait.h> #include <sys/stat.h> #include <sys/ipc.h> #include <sys/shm.h> #include <sys/msg.h> #include <sys/sem.h> #include <sys/socket.h> #include <arpa/inet.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <string.h> #include <stdio.h> #include <stdlib.h> #include <iostream> using namespace std; void err_exit(std::string str) { perror(str.c_str()); exit(EXIT_FAILURE); } void peerClosePrint(std::string str = "peer connect closed") { cout << str << endl; _exit(0); } ssize_t readn(int fd,void *buf,size_t count) { size_t nLeft = count; ssize_t nRead = 0; char *ptr = static_cast<char *>(buf); while (nLeft > 0) { if ((nRead = read(fd,ptr,nLeft)) < 0) { //1點(diǎn)東西都沒(méi)讀 if (nLeft == count) { return ⑴; //error } else { break; //error, return amount read so far } } else if (nRead == 0) { break; //EOF } nLeft -= nRead; ptr += nRead; } return count - nLeft; } ssize_t writen(int fd, const void *buf, size_t count) { size_t nLeft = count; ssize_t nWritten; const char *ptr = static_cast<const char *>(buf); while (nLeft > 0) { if ((nWritten = write(fd,ptr,nLeft)) < 0) { //1點(diǎn)東西都沒(méi)寫(xiě) if (nLeft == count) { return ⑴; //error } else { break; //error, return amount write so far } } else if (nWritten == 0) { break; //EOF } nLeft -= nWritten; ptr += nWritten; } return count - nWritten; } //只是查看1下網(wǎng)絡(luò)中的數(shù)據(jù),其實(shí)不是將之真正取走:MSG_PEEK ssize_t recv_peek(int fd, void *buf, size_t count) { int nRead = 0; //如果讀取網(wǎng)絡(luò)數(shù)據(jù)出錯(cuò),則繼續(xù)讀取 while ((nRead = recv(fd,buf,count,MSG_PEEK)) == ⑴); return nRead; } ssize_t readline(int fd, void *buf, size_t maxline) { char *pBuf = (char *)buf; int nLeft = maxline; while (true) { //查看緩沖區(qū)中的數(shù)據(jù),其實(shí)不真正取走 int nTestRead = recv_peek(fd,pBuf,nLeft); //檢測(cè)這次讀來(lái)的數(shù)據(jù)中是不是包括' '; //如果有,則將之全部讀取出來(lái) for (int i = 0; i < nTestRead; ++i) { if (pBuf[i] == ' ') { //真實(shí)的從緩沖區(qū)中將數(shù)據(jù)取走 if (readn(fd,pBuf,i+1) != i+1) { err_exit("readn error"); } else { return i + 1; } } } //如果這次讀的緩沖區(qū)中沒(méi)有' ' //如果讀超了:讀道德數(shù)目大于1行最大數(shù),則做異常處理 if (nTestRead > nLeft) { exit(EXIT_FAILURE); } nLeft -= nTestRead; //若緩沖區(qū)沒(méi)有' ',則將剩余的數(shù)據(jù)讀走 if (readn(fd,pBuf,nTestRead) != nTestRead) { exit(EXIT_FAILURE); } pBuf += nTestRead; } return ⑴; } #endif // COMMEN_H_INCLUDED

2-Mafile文件

CC = g++ CPPFLAGS = -Wall -g -pthread BIN = server client SOURCES = $(BIN.=.cpp) .PHONY: clean all all: $(BIN) $(BIN): $(SOURCES) clean: -rm -rf $(BIN) bin/ obj/ core


生活不易,碼農(nóng)辛苦
如果您覺(jué)得本網(wǎng)站對(duì)您的學(xué)習(xí)有所幫助,可以手機(jī)掃描二維碼進(jìn)行捐贈(zèng)
程序員人生
------分隔線----------------------------
分享到:
------分隔線----------------------------
關(guān)閉
程序員人生
主站蜘蛛池模板: 尤物视频黄 | 最新国产露脸在线观看 | 欧美日韩亚洲综合 | 久久久精品网站 | 成人免费视频网 | 国产精品久久久久久久久久新婚 | 国产欧美123 | 日本久久免费 | 久久精品免费观看 | 国产原创精品视频 | 久久99国产精品 | 国产精品爽爽爽爽爽爽在线观看 | 成人看片在线观看 | 国产a一区 | 欧美成人精品一区 | 国内av毛片 | 人人九九精品 | 日韩高清在线 | 日韩在线观看视频免费 | 日韩精品久久久久久 | 成人国产精品免费观看 | 亚洲国产高清视频 | 91超碰在线播放 | 尤物yw | 欧美在线不卡视频 | 欧美综合国产 | 五月婷婷综合色 | 久久久一区二区三区 | 亚洲国产中文在线 | 日本欧美视频 | 日产精品久久久一区二区开放时间 | 久久国产精品久久久久久久久久 | 日韩和的一区二区 | 亚洲国产精品久久久久秋霞不卡 | 日本精品视频网站 | 久久婷婷色 | 国产成人精品久久二区二区91 | 国产精品久久久久久妇 | 国产成人精品av | 中文字幕二区 | 国产美女高潮 |