日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 >

基本套接字总结(@function)

發(fā)布時(shí)間:2025/5/22 16 豆豆
生活随笔 收集整理的這篇文章主要介紹了 基本套接字总结(@function) 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

最近學(xué)習(xí)了下UNIX下的網(wǎng)絡(luò)編程。為了以后查詢方便,總結(jié)在這里。

首先套接字的地址定義:

   IPv4地址和IPv6地址定義見<netinet/in.h>頭文件定義。為了能夠順利轉(zhuǎn)換不同的套接字內(nèi)容,可以查看<sys/socket.h>中定義的通用套接字struct sockaddr;在使用過成中我們可以將struct sockaddr_in 和 sockaddr_in6直接強(qiáng)制轉(zhuǎn)換成struct sockaddr.

連接過程中我們需要人工指定對(duì)應(yīng)網(wǎng)絡(luò)地址。而不同的主機(jī)實(shí)現(xiàn)中存在不同的數(shù)據(jù)格式(big-endian OR little-endian),我們需要通過如下轉(zhuǎn)換函數(shù)來保證數(shù)據(jù)轉(zhuǎn)換過程中的正確性。

函數(shù)列表如下:   

#include <netinet/in.h> //from host byte order to network byte order uint16_t htons(uint16_t host16bitvalue)
//servaddr.sin_addr.s_addr = htonl(INADDR_ANY); ? uint32_t htonl(uint32_t host32bitvalue)
//from network byte order to host byte order uint16_t ntohs(uint16_t host16bitvalue) uint16_t ntohl(uint16_t host16bitvalue)

?地址轉(zhuǎn)換函數(shù)使用:

#include <arpa/inet.h>int inet_pton(int family, const char* strptr, void *addrptr);  //成功返回1,格式錯(cuò)誤返回0,出錯(cuò)返回-1
//示例::Inet_pton(AF_INET, argv[1], &serveraddr.sin_addr);
const char* inet_ntop(int family, const void*addrptr, char *strptr, size_t len); //len參數(shù)指出緩存區(qū)的大小,避免出現(xiàn)溢出

?

基本TCP套接字編程示例程序如下(這里我們r(jià)ead,write等系統(tǒng)IO操作來實(shí)現(xiàn)網(wǎng)絡(luò)回射服務(wù)):

其中涉及到的網(wǎng)絡(luò)編程函數(shù)包括:socket(),bind(),bzero(),inet_pton(), listen(),connect(),accept()

服務(wù)過程中socket()指定所要進(jìn)行操作的網(wǎng)絡(luò)服務(wù)是什么, socket(指定協(xié)議族, 操作類型, 采用協(xié)議)

協(xié)議族包括:AF_INET:Pv4;  AF_INET6:IPv6;  AF_LOCAL:UNIX域協(xié)議;  AF_ROUTE:路由套接字;  AF_KEY:密鑰套接字

操作類型:SOCK_STREAM:字節(jié)流;  SOCK_DGRAM:數(shù)據(jù)報(bào);  SOCK_SEQPACKET:有序分組;  SOCK_RAW:原始套接字

采用協(xié)議:IPPROTO_TCP...._UDP...._SCTP

?

需要注意的問題:

  Fork子進(jìn)程后,connfd和listenfd的引用次數(shù)變成2,所以需要在子進(jìn)程和父進(jìn)程中同時(shí)關(guān)閉才能保證完全關(guān)閉。

  多個(gè)子進(jìn)程并發(fā)后,會(huì)在服務(wù)器上產(chǎn)生大量的僵死進(jìn)程,從而使得大量的服務(wù)器資源浪費(fèi)。為此我們需要捕獲僵死進(jìn)程的信號(hào)SIGCHLD,并做相應(yīng)的處理。因?yàn)閁NIX中信號(hào)不排隊(duì)的設(shè)計(jì),采用wait處理完第一個(gè)僵死進(jìn)程的信號(hào)后其余的進(jìn)程信號(hào)丟失。從而清理不徹底。為此,這里采用waitpid函數(shù)進(jìn)行處理。

首先,服務(wù)器程序:

#include "unp.h" #include <stdio.h> #include <stdlib.h>void str_echo(int sockfd); Sigfunc* signal1(int signo, Sigfunc* func); void sig_child(int signo); int main(int argc, char** argv){int listenfd, connfd;char buff[MAXLINE];pid_t childpid;socklen_t clilen;struct sockaddr_in cliaddr, servaddr;//<sys/socket.h>//int socket(int family, int type, int protocal);listenfd = Socket(AF_INET, SOCK_STREAM, 0);bzero(&servaddr, sizeof(struct sockaddr_in));servaddr.sin_family = AF_INET;servaddr.sin_addr.s_addr = htonl(INADDR_ANY);servaddr.sin_port = htons(SERV_PORT);Bind(listenfd, (SA*) &servaddr, sizeof(servaddr));Listen(listenfd, LISTENQ);//working with the signal1(SIGCHLD, sig_child);while(1){clilen = sizeof(cliaddr);connfd = Accept(listenfd, (SA*)&cliaddr, &clilen);if ((childpid = Fork()) == 0){Close(listenfd);str_echo(connfd);exit(0);}Close(connfd);}return 0; }void str_echo(int sockfd){ssize_t n;char buf[MAXLINE]; again:while((n = read(sockfd, buf, MAXLINE) ) > 0)Write(sockfd, buf, n);if (n < 0 && errno == EINTR)goto again;else if (n < 0)err_sys("str_echo: read error");}Sigfunc* signal1(int signo, Sigfunc* func){struct sigaction act, oact;act.sa_handler = func;sigemptyset(&act.sa_mask);act.sa_flags = 0;if ( signo == SIGALRM){ #ifdef SA_INTERRUPT//設(shè)定中斷,使該信號(hào)處理過程中能夠中斷:act.sa_flags |= SA_INTERRUPT; #endif}else{ #ifdef SA_RESTART//信號(hào)處理,設(shè)置SA_RESTART標(biāo)志,使得內(nèi)核對(duì)失敗的//系統(tǒng)調(diào)用自動(dòng)重啟。act.sa_flags |= SA_RESTART; #endif}if (sigaction(signo, &act, &oact) < 0){return SIG_ERR;}return (oact.sa_handler); }void sig_child(int signo){pid_t pid;int stat;/*********************************************** #inlcude <sys/wait.h>這里使用wait函數(shù)只能處理第一個(gè)返回的僵死進(jìn)程,因?yàn)槠銾NIX系統(tǒng)信號(hào)實(shí)現(xiàn)中信號(hào)是不進(jìn)行排隊(duì)的。所以我們采用waitpid并且設(shè)定最后的選項(xiàng)為WNOHANG.表示內(nèi)核在沒有進(jìn)程時(shí)不僅行阻塞。***********************************************/// --- pid = wait(&stat);while(( pid = waitpid(-1, &stat, WNOHANG)) > 0)printf("child %d terminated.\n", pid);return; }

客戶端程序:

#include "unp.h" #include <stdio.h> #include <stdlib.h>int str_cli1(FILE *fp, int sockfd);int main(int argc, char** argv){int sockfd[5];struct sockaddr_in serveraddr;int i;if (argc < 2)err_quit("Use: clisocket <IPaddress>");for (i = 0; i <5; ++i){sockfd[i] = Socket(AF_INET, SOCK_STREAM,0);bzero(&serveraddr, sizeof(struct sockaddr_in));serveraddr.sin_family = AF_INET;serveraddr.sin_port = htons(SERV_PORT);Inet_pton(AF_INET, argv[1], &serveraddr.sin_addr);Connect(sockfd[i], (SA*)&serveraddr, sizeof(serveraddr));}str_cli(stdin, sockfd[0]);exit(0); }int str_cli1(FILE *fp, int sockfd){char sendline[MAXLINE], recvline[MAXLINE];while(Fgets(sendline, MAXLINE, fp) != NULL){Writen(sockfd, sendline, strlen(sendline));if (Readline(sockfd, recvline, MAXLINE) == 0)err_quit("str_cli: server terminated prematurely");Fputs(recvline, stdout);} }

?

轉(zhuǎn)載于:https://www.cnblogs.com/BeDPS/p/3693088.html

總結(jié)

以上是生活随笔為你收集整理的基本套接字总结(@function)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。