標籤:socket linux udp cc++ 伺服器
UDP特點
無串連,面向資料報(基於訊息,不會粘包)的Data Transmission Service;
不可靠(可能會丟包),但一般情況下UDP更加高效;
UDP客戶/服務基本模型
UDP基礎API
1.Recvfrom
SYNOPSIS
#include <sys/types.h> #include <sys/socket.h> ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr *src_addr, socklen_t *addrlen);
2.Sendto
SYNOPSIS
#include <sys/types.h> #include <sys/socket.h> ssize_t sendto(int sockfd, const void *buf, size_t len, int flags, const struct sockaddr *dest_addr, socklen_t addrlen);
實踐:一個簡陋的echo回聲server/client
//server.cpp#include "commen.h"int main(){ //建立UDP socket int sockfd = socket(AF_INET,SOCK_DGRAM,0); if (sockfd == -1) { err_exit("socket error"); } //填寫server端資訊 struct sockaddr_in serverAddr; serverAddr.sin_family = AF_INET; serverAddr.sin_port = htons(9001); serverAddr.sin_addr.s_addr =INADDR_ANY; //綁定server端連接埠號碼 if (bind(sockfd,(struct sockaddr *)&serverAddr,sizeof(serverAddr)) == -1) { err_exit("bind error"); } char buf[BUFSIZ]; struct sockaddr_in peerAddr; socklen_t peerLen = sizeof(peerAddr); while (true) { memset(buf,0,sizeof(buf)); int readCount = 0; //接收從用戶端發送過來的資料 if ((readCount = recvfrom(sockfd,buf,sizeof(buf),0,(struct sockaddr *)&peerAddr,&peerLen)) == -1) { err_exit("recvfrom error"); } //列印用戶端資訊 cout << "Client: " << endl; cout << "\tsin_port: " << ntohs(peerAddr.sin_port) << endl; cout << "\tsin_addr: " << inet_ntoa(peerAddr.sin_addr) << endl; //將用戶端發送來的資訊回寫回去 if (sendto(sockfd,buf,sizeof(buf),0,(struct sockaddr *)&peerAddr,peerLen) == -1) { err_exit("sendto error"); } buf[readCount] = 0; //輸出到螢幕 fputs(buf,stdout); } return 0;}
//client.cpp#include "commen.h"int main(){ //建立UDP socket int sockfd = socket(AF_INET,SOCK_DGRAM,0); if (sockfd == -1) { err_exit("socket error"); } //填寫server端資訊 struct sockaddr_in serverAddr; serverAddr.sin_family = AF_INET; serverAddr.sin_port = htons(9001); serverAddr.sin_addr.s_addr = inet_addr("127.0.0.1"); char buf[BUFSIZ]; //從鍵盤接收資料 while (fgets(buf,sizeof(buf),stdin) != NULL) { //向server端傳送資料 if (sendto(sockfd,buf,strlen(buf),0,(struct sockaddr *)&serverAddr,sizeof(serverAddr)) == -1) { err_exit("sendto error"); } memset(buf,0,sizeof(buf)); int readCount = 0; //從server端接收資料,並且忽略server端資訊recvfrom(xx,xx,xx,xx,NULL,NULL) if ((readCount = recvfrom(sockfd,buf,sizeof(buf),0,NULL,NULL)) == -1) { err_exit("recvfrom error"); } buf[readCount] = 0; //將資料寫到螢幕 fputs(buf,stdout); } 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 <sys/select.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"){ cerr << str << endl; _exit(0);}#endif // COMMEN_H_INCLUDED
附-Makefile
CC = g++ CPPFLAGS = -Wall -g -pthreadBIN = server clientSOURCES = $(BIN.=.cpp).PHONY: clean all all: $(BIN)clean: -rm -rf $(BIN) bin/ obj/ core
Socket編程實踐(13) --UDP編程基礎(1)