多多色-多人伦交性欧美在线观看-多人伦精品一区二区三区视频-多色视频-免费黄色视屏网站-免费黄色在线

國內最全IT社區平臺 聯系我們 | 收藏本站
阿里云優惠2
您當前位置:首頁 > php開源 > php教程 > Socket 編程實踐(5) --p2p聊天程序設計與實現

Socket 編程實踐(5) --p2p聊天程序設計與實現

來源:程序員人生   發布時間:2015-01-02 09:56:17 閱讀次數:3265次

1個短連接的client

//短鏈接客戶端 int main() { int loopCount = 20; char sendBuf[BUFSIZ] = {0}; char recvBuf[BUFSIZ] = {0}; for (int i = 0; i < loopCount; ++i) { sprintf(sendBuf,"Hello Server %d ",i); //創建新的套接字 int sockfd = socket(AF_INET,SOCK_STREAM,0); if (sockfd == ⑴) { err_exit("socket error"); } //填寫好服務器地址及其端口號 struct sockaddr_in serverAddr; serverAddr.sin_family = AF_INET; serverAddr.sin_port = htons(8002); //本機測試,填寫127.0.0.1(回環地址) serverAddr.sin_addr.s_addr = inet_addr("127.0.0.1"); //連接server if (connect(sockfd,(struct sockaddr *)&serverAddr,sizeof(serverAddr)) == ⑴) { err_exit("connect error"); } //向server發送數據 if (write(sockfd,sendBuf,strlen(sendBuf)) == ⑴) { err_exit("write socket error"); } int readCount = 0; //從server接收數據 if ((readCount = read(sockfd,recvBuf,sizeof(recvBuf))) < 0) { err_exit("read socket error"); } //將其回寫到終端 write(STDOUT_FILENO,recvBuf,strlen(recvBuf)); close(sockfd); } return 0; }


注:server端基于上1篇博客中的代碼


點對點聊天程序設計與實現

點對點聊天程序功能說明:

 

 

代碼實現與說明

//serever端完全代碼與說明 #include "commen.h" int main() { //安裝信號接收函數 signal(SIGUSR1,onSignal); //創建監聽套接字 int sockfd = socket(AF_INET,SOCK_STREAM,0); if (sockfd == ⑴) { err_exit("socket error"); } //添加地址復用 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(8001); serverAddr.sin_addr.s_addr = INADDR_ANY; //綁定本機的任意1個IP地址 if (bind(sockfd,(struct sockaddr *)&serverAddr,sizeof(serverAddr)) == ⑴) { err_exit("bind error"); } //啟用監聽套接字 //1旦調用了listen,則sockfd編程被動套接字 -> 等待客戶真個連接(只能接受連接,不能發送連接) if (listen(sockfd,SOMAXCONN) == ⑴) { err_exit("listen error"); } //如果沒有客戶端鏈接的來到,則該系統調用會1直阻塞 struct sockaddr_in peerAddr; socklen_t peerLen = sizeof(peerAddr); int peerSockfd = accept(sockfd, (struct sockaddr *)&peerAddr,&peerLen); if (peerSockfd == ⑴) { err_exit("accept error"); } //客戶端來到 cout << "Client Connected:" << endl; cout << " peerAddr.sin_addr: " << inet_ntoa(peerAddr.sin_addr) << endl; cout << " peerAddr.sin_port: " << ntohs(peerAddr.sin_port) << endl; //創建子進程 pid_t pid = fork(); if (pid == ⑴) { err_exit("fork error"); } //父進程:從客戶端接收數據 -> 打印到屏幕 if (pid > 0) { close(STDIN_FILENO); //關閉沒用的文件描寫符 char recvBuf[BUFSIZ] = {0}; int readCount = 0; //從客戶端接收數據 while ((readCount = read(peerSockfd,recvBuf,sizeof(recvBuf))) > 0) { recvBuf[readCount] = 0; //將其打印到屏幕 fprintf(stdout,"%s",recvBuf); memset(recvBuf,0,sizeof(recvBuf)); } //對端已關閉 if (readCount == 0) { close(peerSockfd); //關閉通訊結點 cout << "peer connect closed" << endl; //發送SIGUSR1信號給子進程,將子進程殺死 kill(pid,SIGUSR1); _exit(0); } //接收毛病 else if (readCount == ⑴) { close(peerSockfd); //發送SIGUSR1信號給子進程,將子進程殺死 kill(pid,SIGUSR1); err_exit("read error"); } } else if (pid == 0) //子進程:從鍵盤接收數據 -> 寫到客戶端 { close(STDOUT_FILENO); char sendBuf[BUFSIZ] = {0}; //從鍵盤接收數據 while (true) { if (fgets(sendBuf,sizeof(sendBuf),stdin) == NULL) { break; } else if (strncmp(sendBuf,"quit",4) == 0) { close(peerSockfd); kill(getppid(),SIGUSR2); break; } //發送到client端 if (write(peerSockfd,sendBuf,strlen(sendBuf)) == ssize_t(⑴)) { close(peerSockfd); err_exit("write socket error"); } memset(sendBuf,0,sizeof(sendBuf)); } } close(sockfd); return 0; }

//client端完全代碼與說明 #include "commen.h" int main() { signal(SIGUSR1,onSignal); //創建新的套接字 int sockfd = socket(AF_INET,SOCK_STREAM,0); if (sockfd == ⑴) { err_exit("socket error"); } //填寫server端IP地址及其端口號 struct sockaddr_in serverAddr; serverAddr.sin_family = AF_INET; serverAddr.sin_port = htons(8001); serverAddr.sin_addr.s_addr = inet_addr("127.0.0.1"); //連接到server if (connect(sockfd,(struct sockaddr *)&serverAddr,sizeof(serverAddr)) == ⑴) { err_exit("connect error"); } pid_t pid = fork(); if (pid == ⑴) { err_exit("fork error"); } //父進程:從鍵盤接收數據 -> 將之發送給server端 if (pid > 0) { close(STDOUT_FILENO); char sendBuf[BUFSIZ] = {0}; //從鍵盤接收數據 while (true) { if (fgets(sendBuf,sizeof(sendBuf),stdin) == NULL) { break; } else if (strncmp(sendBuf,"quit",4) == 0) { close(sockfd); //發送SIGUSR1信號給子進程,將其關閉 kill(pid,SIGUSR1); _exit(0); } //發送到server端 if (write(sockfd,sendBuf,strlen(sendBuf)) == ssize_t(⑴)) { close(sockfd); err_exit("write socket error"); } memset(sendBuf,0,sizeof(sendBuf)); } } else if (pid == 0) //子進程:從server端接收數據,將其打印到屏幕 { close(STDIN_FILENO); char recvBuf[BUFSIZ] = {0}; int readCount = 0; //從server端接收數據 while ((readCount = read(sockfd,recvBuf,sizeof(recvBuf))) > 0) { recvBuf[readCount] = 0; //將其打印到屏幕 fprintf(stdout,"%s",recvBuf); memset(recvBuf,0,sizeof(recvBuf)); } if (readCount == 0) { close(sockfd); cout << "peer connect closed" << endl; //發送SIGUSR2信號給父進程,將其關閉 kill(getppid(),SIGUSR2); _exit(0); } else if (readCount == ⑴) { close(sockfd); err_exit("read error"); } } return 0; }


可以看出,此時既沒有端口占用,也沒有僵尸進程!



-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); } struct SendStruct { int type; char text[BUFSIZ]; }; void onSignal(int signalNumber) { switch (signalNumber) { case SIGUSR1: cout << "child receive SIGUSR1" << signalNumber << endl; _exit(0); case SIGUSR2: cout << "parent receive SIGUSR2: " << signalNumber << endl; _exit(0); default: cout << "RECV OTHRER SIGNAL" << endl; } } #endif // COMMEN_H_INCLUDED

附-Makefile

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

生活不易,碼農辛苦
如果您覺得本網站對您的學習有所幫助,可以手機掃描二維碼進行捐贈
程序員人生
------分隔線----------------------------
分享到:
------分隔線----------------------------
關閉
程序員人生
主站蜘蛛池模板: 欧美巨大另类极品videosbest | 一区二区三区视频在线播放 | 天堂69亚洲精品中文字幕 | 欧美亚洲综合另类在线观看 | 国产亚洲精品久久久久久 | 欧美一级爱操视频 | 琪琪jav| 亚洲欧美一区二区三区另类 | 一级特黄aa毛片免费观看 | 手机在线视频观看 | 精品亚洲成a人在线观看 | 欧美激情精品久久久久 | 国产精品久久久久久久久久久久久久 | 男人午夜视频在线观看 | 亚洲高清成人 | 久久受www免费人成_看片中文 | 999国产精品亚洲77777 | 亚洲国产精品人久久 | 亚洲精品久久77777 | 亚洲十欧美十日韩十国产 | 国内精品久久影视 | 亚洲福利视频一区二区 | 亚洲精品欧美日韩 | 97午夜理伦影院在线观看 | 亚洲一区第一页 | 亚洲图片综合 | 久久久一区二区三区不卡 | 欧美日韩中文国产一区二区三区 | 国产精品成人网 | 大香焦伊人久久 | 国产精品香蕉在线观看不卡 | 精品女人| www.久久精品视频 | 国产一二三四区中 | 欧美性色网 | 亚洲最新 | 欧美一线天| 亚洲国产欧美目韩成人综合 | 免费在线播放毛片 | 亚洲国产最新在线一区二区 | 亚洲精品久久久久影 |