Socket------基于TCP的編程實(shí)例

流程:

服務(wù)器端先初始化Socket,然后與端口綁定(bind),對端口進(jìn)行監(jiān)聽(listen),調(diào)用accept阻塞,等待客戶端連接。

在這時(shí)如果有個(gè)客戶端初始化一個(gè)Socket,然后連接服務(wù)器(connect),如果連接成功,這時(shí)客戶端與服務(wù)器端的連接就建立了。客戶端發(fā)送數(shù)據(jù)請求,服務(wù)器端接收請求并處理請求,然后把回應(yīng)數(shù)據(jù)發(fā)送給客戶端,客戶端讀取數(shù)據(jù),最后關(guān)閉連接,一次交互結(jié)束。


基于TCP的Socket通信流程圖

Socket編程實(shí)例

服務(wù)器端:一直監(jiān)聽本機(jī)的8000號端口,如果收到連接請求,將接收請求并接收客戶端發(fā)來的消息,并向客戶端返回消息。

/* File Name: server.c */?

?#include

#include

#include

#include

#include

#include

#include

#define DEFAULT_PORT 8000?

#define MAXLINE 4096?

int main(int argc, char** argv)?

{?

????????int? ? socket_fd, connect_fd;?

????????struct sockaddr_in? ? servaddr;?

????????char? ? buff[4096];?

????????int? ? n;?

????????//初始化Socket?

????????if( (socket_fd = socket(AF_INET, SOCK_STREAM, 0)) == -1 ) {?

????????????????printf("create socket error: %s(errno: %d)\n",strerror(errno),errno);?

????????????????exit(0);?

????????}?

????????//初始化?

????????memset(&servaddr, 0, sizeof(servaddr));?

????????servaddr.sin_family = AF_INET;?

????????servaddr.sin_addr.s_addr = htonl(INADDR_ANY);//IP地址設(shè)置成INADDR_ANY,讓系統(tǒng)自動(dòng)獲取本機(jī)的IP地址。?

????????servaddr.sin_port = htons(DEFAULT_PORT);//設(shè)置的端口為DEFAULT_PORT?

????????//將本地地址綁定到所創(chuàng)建的套接字上?

????????if( bind(socket_fd, (struct sockaddr*)&servaddr, sizeof(servaddr)) == -1) {?

????????????????printf("bind socket error: %s(errno: %d)\n",strerror(errno),errno);?

????????????????exit(0);?

? ? ? ? }?

? ??????//開始監(jiān)聽是否有客戶端連接?

????????if( listen(socket_fd, 10) == -1) {?

????????????????printf("listen socket error: %s(errno: %d)\n",strerror(errno),errno);?

????????????????exit(0);?

????????}?

????????printf("======waiting for client's request======\n");?

????????while(1) {?

? ??????????????//阻塞直到有客戶端連接,不然多浪費(fèi)CPU資源。?

????????????????if( (connect_fd = accept(socket_fd, (struct sockaddr*)NULL, NULL)) == -1) {?

????????????????????????printf("accept socket error: %s(errno: %d)",strerror(errno),errno);?

????????????????????????continue;?

????????????????}?

????????????????//接受客戶端傳過來的數(shù)據(jù)?

????????????????n = recv(connect_fd, buff, MAXLINE, 0);?

????????????????//向客戶端發(fā)送回應(yīng)數(shù)據(jù)?

????????????????if(!fork()) {? /*紫禁城*/?

????????????????????????if(send(connect_fd, "Hello,you are connected!\n", 26,0) == -1)? {

????????????????????????????????perror("send error");?

? ? ? ? ? ? ? ? ? ? ? ? }

????????????????????????close(connect_fd);?

????????????????????????exit(0);?

????????????????}?

????????????????buff[n] = '\0';?

????????????????printf("recv msg from client: %s\n", buff);?

????????????????close(connect_fd);?

????????}?

????????close(socket_fd);?

}?


客戶端:/* File Name: client.c */

?#include

#include

#include

#include

#include

#include

#include

#define MAXLINE 4096

?int main(int argc, char** argv)? ?{?

?????????int sockfd, n,rec_len;

????????char recvline[4096], sendline[4096];?

?????????char buf[MAXLINE];?

?????????struct sockaddr_in servaddr;?

?????????if( argc != 2)? {

?????????????printf("usage: ./client\n");

? ? ? ? ? ? ?exit(0);?

????????}?

????????if( (sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {?

????????????????printf("create socket error: %s(errno: %d)\n", strerror(errno),errno);?

????????????????exit(0);?

????????}?

????????memset(&servaddr, 0, sizeof(servaddr));?

????????servaddr.sin_family = AF_INET;?

????????servaddr.sin_port = htons(8000);?

????????if( inet_pton(AF_INET, argv[1], &servaddr.sin_addr) <= 0) {?

????????????????printf("inet_pton error for %s\n",argv[1]);?

????????????????exit(0);?

????????}?

????????if( connect(sockfd, (struct sockaddr*)&servaddr, sizeof(servaddr)) < 0 ) {?

????????????????printf("connect error: %s(errno: %d)\n",strerror(errno),errno);?

????????????????exit(0);?

????????}?

????????printf("send msg to server: \n");?

????????fgets(sendline, 4096, stdin);?

????????if( send(sockfd, sendline, strlen(sendline), 0) < 0)?

????????{?

????????????????printf("send msg error: %s(errno: %d)\n", strerror(errno), errno);?

????????????????exit(0);?

????????}?

????????if((rec_len = recv(sockfd, buf, MAXLINE,0)) == -1)? {?

????????????????perror("recv error");?

????????????????exit(1);?

????????}?

????????buf[rec_len]? = '\0';?

????????printf("Received : %s ",buf);?

????????close(sockfd);?

????????exit(0);?

}?


inet_pton 函數(shù)

inet_pton 是Linux下IP地址轉(zhuǎn)換函數(shù),可以在將IP地址在“點(diǎn)分十進(jìn)制”和“整數(shù)”之間轉(zhuǎn)換 ,是inet_addr的擴(kuò)展。

int inet_pton(int af, const char *src, void *dst);//轉(zhuǎn)換字符串到網(wǎng)絡(luò)地址:?

第一個(gè)參數(shù)af是地址族,轉(zhuǎn)換后存在dst中

af = AF_INET:src為指向字符型的地址,即ASCII的地址的首地址(ddd.ddd.ddd.ddd格式的),函數(shù)將該地址轉(zhuǎn)換為in_addr的結(jié)構(gòu)體,并復(fù)制在*dst中

af =AF_INET6:src為指向IPV6的地址,函數(shù)將該地址轉(zhuǎn)換為in6_addr的結(jié)構(gòu)體,并復(fù)制在*dst中

如果函數(shù)出錯(cuò)將返回一個(gè)負(fù)值,并將errno設(shè)置為EAFNOSUPPORT,如果參數(shù)af指定的地址族和src格式不對,函數(shù)將返回0。


測試:

編譯server.c

gcc -o server server.c

啟動(dòng)進(jìn)程:

./server

顯示結(jié)果:

======waiting for client's request======

并等待客戶端連接。

編譯 client.c

gcc -o client server.c

客戶端去連接server:

./client 127.0.0.1?

等待輸入消息

發(fā)送一條消息,輸入:c++

此時(shí)服務(wù)器端看到:

客戶端收到消息:

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容