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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

TCP 客户端和服务器端

發布時間:2023/11/30 编程问答 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 TCP 客户端和服务器端 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

轉自:http://blog.csdn.net/itcastcpp/article/details/39047265

前面幾篇中實現的client每次運行只能從命令行讀取一個字符串發給服務器,再從服務器收回來,現在我們把它改成交互式的,不斷從終端接受用戶輸入并和server交互。

?

[cpp]?view plain?copy
  • /*?client.c?*/??
  • #include?<stdio.h>??
  • #include?<string.h>??
  • #include?<unistd.h>??
  • #include?<netinet/in.h>??
  • #include?"wrap.h"??
  • ???
  • #define?MAXLINE?80??
  • #define?SERV_PORT?8000??
  • ???
  • int?main(int?argc,?char?*argv[])??
  • {??
  • ?????????structsockaddr_in?servaddr;??
  • ?????????charbuf[MAXLINE];??
  • ?????????intsockfd,?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("theother?side?has?been?closed.\n");??
  • ???????????????????else??
  • ????????????????????????????Write(STDOUT_FILENO,buf,?n);??
  • ?????????}??
  • ???
  • ?????????Close(sockfd);??
  • ?????????return0;??
  • }??


  • 編譯并運行server和client,看看是否達到了你預想的結果。

    ?

    這時server仍在運行,但是client的運行結果并不正確。原因是什么呢?仔細查看server.c可以發現,server對每個請求只處理一次,應答后就關閉連接,client不能繼續使用這個連接發送數據。但是client下次循環時又調用write發數據給server,write調用只負責把數據交給TCP發送緩沖區就可以成功返回了,所以不會出錯,而server收到數據后應答一個RST段,client收到RST段后無法立刻通知應用層,只把這個狀態保存在TCP協議層。client下次循環又調用write發數據給server,由于TCP協議層已經處于RST狀態了,因此不會將數據發出,而是發一個SIGPIPE信號給應用層,SIGPIPE信號的缺省處理動作是終止程序,所以看到上面的現象。

    ?

    為了避免client異常退出,上面的代碼應該在判斷對方關閉了連接后break出循環,而不是繼續write。另外,有時候代碼中需要連續多次調用write,可能還來不及調用read得知對方已關閉了連接就被SIGPIPE信號終止掉了,這就需要在初始化時調用sigaction處理SIGPIPE信號,如果SIGPIPE信號沒有導致進程異常退出,write返回-1并且errno為EPIPE。

    ?

    另外,我們需要修改server,使它可以多次處理同一客戶端的請求。

    ?

    [cpp]?view plain?copy
  • /*?server.c?*/??
  • #include?<stdio.h>??
  • #include?<string.h>??
  • #include?<netinet/in.h>??
  • #include?"wrap.h"??
  • ???
  • #define?MAXLINE?80??
  • #define?SERV_PORT?8000??
  • ???
  • int?main(void)??
  • {??
  • ?????????structsockaddr_in?servaddr,?cliaddr;??
  • ?????????socklen_tcliaddr_len;??
  • ?????????intlistenfd,?connfd;??
  • ?????????charbuf[MAXLINE];??
  • ?????????charstr[INET_ADDRSTRLEN];??
  • ?????????inti,?n;??
  • ???
  • ?????????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);??
  • ???
  • ?????????printf("Acceptingconnections?...\n");??
  • ?????????while(1)?{??
  • ???????????????????cliaddr_len=?sizeof(cliaddr);??
  • ???????????????????connfd=?Accept(listenfd,??
  • ?????????????????????????????????????(structsockaddr?*)&cliaddr,?&cliaddr_len);??
  • ???????????????????while(1)?{??
  • ????????????????????????????n=?Read(connfd,?buf,?MAXLINE);??
  • ????????????????????????????if(n?==?0)?{??
  • ?????????????????????????????????????printf("theother?side?has?been?closed.\n");??
  • ?????????????????????????????????????break;??
  • ????????????????????????????}??
  • ????????????????????????????printf("receivedfrom?%s?at?PORT?%d\n",??
  • ???????????????????????????????????inet_ntop(AF_INET,&cliaddr.sin_addr,?str,?sizeof(str)),??
  • ???????????????????????????????????ntohs(cliaddr.sin_port));??
  • ?????
  • ????????????????????????????for(i?=?0;?i?<?n;?i++)??
  • ?????????????????????????????????????buf[i]=?toupper(buf[i]);??
  • ????????????????????????????Write(connfd,buf,?n);??
  • ???????????????????}??
  • ???????????????????Close(connfd);??
  • ?????????}??
  • }??

  • ?

    經過上面的修改后,客戶端和服務器可以進行多次交互了。

    ?

    前面幾篇中實現的client每次運行只能從命令行讀取一個字符串發給服務器,再從服務器收回來,現在我們把它改成交互式的,不斷從終端接受用戶輸入并和server交互。

    ?

    [cpp]?view plain?copy
  • /*?client.c?*/??
  • #include?<stdio.h>??
  • #include?<string.h>??
  • #include?<unistd.h>??
  • #include?<netinet/in.h>??
  • #include?"wrap.h"??
  • ???
  • #define?MAXLINE?80??
  • #define?SERV_PORT?8000??
  • ???
  • int?main(int?argc,?char?*argv[])??
  • {??
  • ?????????structsockaddr_in?servaddr;??
  • ?????????charbuf[MAXLINE];??
  • ?????????intsockfd,?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("theother?side?has?been?closed.\n");??
  • ???????????????????else??
  • ????????????????????????????Write(STDOUT_FILENO,buf,?n);??
  • ?????????}??
  • ???
  • ?????????Close(sockfd);??
  • ?????????return0;??
  • }??


  • 編譯并運行server和client,看看是否達到了你預想的結果。

    ?

    這時server仍在運行,但是client的運行結果并不正確。原因是什么呢?仔細查看server.c可以發現,server對每個請求只處理一次,應答后就關閉連接,client不能繼續使用這個連接發送數據。但是client下次循環時又調用write發數據給server,write調用只負責把數據交給TCP發送緩沖區就可以成功返回了,所以不會出錯,而server收到數據后應答一個RST段,client收到RST段后無法立刻通知應用層,只把這個狀態保存在TCP協議層。client下次循環又調用write發數據給server,由于TCP協議層已經處于RST狀態了,因此不會將數據發出,而是發一個SIGPIPE信號給應用層,SIGPIPE信號的缺省處理動作是終止程序,所以看到上面的現象。

    ?

    為了避免client異常退出,上面的代碼應該在判斷對方關閉了連接后break出循環,而不是繼續write。另外,有時候代碼中需要連續多次調用write,可能還來不及調用read得知對方已關閉了連接就被SIGPIPE信號終止掉了,這就需要在初始化時調用sigaction處理SIGPIPE信號,如果SIGPIPE信號沒有導致進程異常退出,write返回-1并且errno為EPIPE。

    ?

    另外,我們需要修改server,使它可以多次處理同一客戶端的請求。

    ?

    [cpp]?view plain?copy
  • /*?server.c?*/??
  • #include?<stdio.h>??
  • #include?<string.h>??
  • #include?<netinet/in.h>??
  • #include?"wrap.h"??
  • ???
  • #define?MAXLINE?80??
  • #define?SERV_PORT?8000??
  • ???
  • int?main(void)??
  • {??
  • ?????????structsockaddr_in?servaddr,?cliaddr;??
  • ?????????socklen_tcliaddr_len;??
  • ?????????intlistenfd,?connfd;??
  • ?????????charbuf[MAXLINE];??
  • ?????????charstr[INET_ADDRSTRLEN];??
  • ?????????inti,?n;??
  • ???
  • ?????????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);??
  • ???
  • ?????????printf("Acceptingconnections?...\n");??
  • ?????????while(1)?{??
  • ???????????????????cliaddr_len=?sizeof(cliaddr);??
  • ???????????????????connfd=?Accept(listenfd,??
  • ?????????????????????????????????????(structsockaddr?*)&cliaddr,?&cliaddr_len);??
  • ???????????????????while(1)?{??
  • ????????????????????????????n=?Read(connfd,?buf,?MAXLINE);??
  • ????????????????????????????if(n?==?0)?{??
  • ?????????????????????????????????????printf("theother?side?has?been?closed.\n");??
  • ?????????????????????????????????????break;??
  • ????????????????????????????}??
  • ????????????????????????????printf("receivedfrom?%s?at?PORT?%d\n",??
  • ???????????????????????????????????inet_ntop(AF_INET,&cliaddr.sin_addr,?str,?sizeof(str)),??
  • ???????????????????????????????????ntohs(cliaddr.sin_port));??
  • ?????
  • ????????????????????????????for(i?=?0;?i?<?n;?i++)??
  • ?????????????????????????????????????buf[i]=?toupper(buf[i]);??
  • ????????????????????????????Write(connfd,buf,?n);??
  • ???????????????????}??
  • ???????????????????Close(connfd);??
  • ?????????}??
  • }??

  • ?

    經過上面的修改后,客戶端和服務器可以進行多次交互了。

    ?

    總結

    以上是生活随笔為你收集整理的TCP 客户端和服务器端的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

    主站蜘蛛池模板: 欧美你懂的 | 激情在线网站 | 国产一区2 | 一区二区三区四区视频 | 国产精品老牛影院99av | 日韩中文欧美 | 亚洲中文字幕无码一区二区三区 | 比利时xxxx性hd极品 | 国产露脸91国语对白 | 91综合网| 黄色一机片 | 欧美日韩中文字幕在线观看 | av大片在线播放 | 国产精品一线 | 国产第一草草影院 | 成人在线网 | 国产在线观看网站 | 国产精品视频全国免费观看 | 黄色aaaaa | 精品国产一级 | 少妇高潮喷水在线观看 | 黄色小视频在线播放 | 带aaa级的网名 | av亚洲在线 | 色小姐综合| 国产一级不卡毛片 | 99久久精品国产一区二区三区 | 久久婷婷综合国产 | 久久性片| 久久综合伊人77777麻豆 | 欧美精品999 | 亚洲欧美另类在线视频 | 国产亚洲欧美视频 | 最新国产精品视频 | 亚洲视频色图 | 一本色道久久综合亚洲精品 | 国产区一二三 | 国产欧美在线一区 | 成年人免费看视频 | 卡通动漫亚洲综合 | 海角国产乱辈乱精品视频 | 亚洲成色在线 | 国产精品日韩电影 | 性欧美videossex精品 | 怡红院成永久免费人全部视频 | 不卡的av在线免费观看 | 先锋影音一区二区三区 | 熟女熟妇伦久久影院毛片一区二区 | 黄色一级片欧美 | 日本一区视频在线 | 午夜吃瓜| 香港三日本8a三级少妇三级99 | 综合五月激情 | 欧美在线激情 | 日日鲁鲁鲁夜夜爽爽狠狠视频97 | 日韩精品中文字幕在线播放 | 性色av免费 | 日本学生初尝黑人巨免费视频 | 波多野结衣在线观看一区 | 欧美老女人bb | 亚洲 欧美 日韩 国产综合 在线 | 国产亚洲精品自拍 | 精品人妻人人做人人爽夜夜爽 | 欧美精品三区 | 亚洲在线视频免费观看 | 在线免费av观看 | 激情拍拍| 亚洲自拍p | 日韩中出在线 | 国产美女久久久久 | 91免费福利 | 黄色在线播放视频 | a级片国产| 快播色图 | 亚洲自拍小视频 | 国产婷婷| 欧美18免费视频 | 亚洲成人一二三区 | 国产视频一二三区 | 一区二区三区日韩 | h片在线 | 色妞色视频一区二区三区四区 | 欧美日韩激情视频在线观看 | 美女隐私黄www网站动漫 | 欧美视频免费看欧美视频 | 香蕉av在线 | 国产精品国产a级 | 欧美少妇b | 黄色成年人 | 福利一区在线 | 亚洲天堂2021av | 成人看片| 国产精品青青草 | 色婷婷电影网 | av2014天堂网 | 91国产免费视频 | 亚洲日本三级 | 欧美猛交免费 | 2018自拍偷拍 |