Linux下socket编程的简单实例
1 服務(wù)器端的socket編程
服務(wù)器端主要的功能,就是創(chuàng)建socket監(jiān)聽,等待客戶端的連接。
基礎(chǔ)的步驟很簡單,如下:
(1) 創(chuàng)建socket;
(2) 綁定地址和端口;
(3) 啟動監(jiān)聽;
(4) 接受客戶端請求;
(5) 讀/寫數(shù)據(jù);
1.1 創(chuàng)建socket:
函數(shù)原型:
1
第一個參數(shù)為socket的協(xié)議族,由一組宏定義表示,一般使用AF_INET,表示使用IPV4協(xié)議。
第二個參數(shù)為socket的類型,主要分為SOCK_STREAM和SOCK_DGRAM,分別對應(yīng)TCP協(xié)議和UDP協(xié)議。
第三個參數(shù)為socket使用的特定協(xié)議,一般對應(yīng)一個協(xié)議族就只有一個協(xié)議,可以使用0表示使用默認的協(xié)議。
函數(shù)返回值為創(chuàng)建的socket文件描述符。-1表示創(chuàng)建失敗。
函數(shù)定義及相關(guān)宏定義在頭文件<sys/socket.h>。
1.2 綁定地址和端口:
函數(shù)原型:
1
第一個參數(shù)為剛剛創(chuàng)建的socket;
第二個參數(shù)是一個結(jié)構(gòu)體sockaddr的指針。但實際使用的時候,根據(jù)協(xié)議的不同,而使用不同的結(jié)構(gòu)。對于TCP來說,使用sockaddr_in。
第三個參數(shù)是第二個參數(shù)的結(jié)構(gòu)體的長度。
sockaddr_in的結(jié)構(gòu)為:
//里面的in_addr結(jié)構(gòu)體:
typedef uint32_t in_addr_t;struct in_addr{in_addr_t s_addr;};1.3 啟動監(jiān)聽:
函數(shù)原型:
int listen(int sockfd, int backlog);
1
第一個參數(shù)為socket文件描述符;
第二個參數(shù)為同時連接數(shù)量;
1.4 接受客戶端請求:
函數(shù)原型:
1
第一個參數(shù)為socket文件描述符;
第二個參數(shù)為sockaddr結(jié)構(gòu)體指針,用來接收客戶端的地址信息。
第三個參數(shù)為第二個參數(shù)的長度。
返回值為對應(yīng)的客戶端socket的文件描述符,失敗則返回-1。
如果沒有特殊設(shè)置的話,accept會阻塞,直接有連接進來或者出錯。
1.5 讀/寫數(shù)據(jù):
有連接進來之后,就可以使用read/write函數(shù)進行通訊了。
1.6 一個簡單的服務(wù)器例子:
#include <stdio.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h>#define PORT 5116 #define BUF_SIZE 256int main(int argc, char** argv) {int fd = socket(AF_INET, SOCK_STREAM, 0);if (fd == -1){printf("created socket error\n");return 0;}struct sockaddr_in addr;addr.sin_family = AF_INET;addr.sin_port = htons(PORT);addr.sin_addr.s_addr = INADDR_ANY;//表示使用本機IPint len = sizeof(addr);if (-1 == bind(fd, (struct sockaddr*)&addr, len)){printf("bind socket fail\n");close(fd);return 0;}listen(fd, 10);int clientFd;struct sockaddr_in clientAddr;int clientLen = sizeof(clientAddr);printf("The server is waiting for connect...\n"); clientFd = accept(fd, (struct sockaddr*)&clientAddr, &clientLen); char szMsg[BUF_SIZE]; int n; if (clientFd > 0){ printf("Accept client from %s:%d\n", inet_ntoa(clientAddr.sin_addr), clientAddr.sin_port); while((n = read(clientFd, szMsg, BUF_SIZE)) > 0){ szMsg[n] = 0; printf("Recv Msg : %s\n", szMsg); } close(clientFd); } close(fd); return 0; }使用gcc編譯,就可以運行,等待客戶端的連接了。
2 客戶端的socket編程
客戶端的功能,就是連接到服務(wù)器,然后就可以進行通訊。所以主要的步驟就是填寫服務(wù)器的地址并進行連接。
(1)創(chuàng)建socket;
(2)連接服務(wù)器;
(3)讀/寫數(shù)據(jù);
2.1 連接服務(wù)器
創(chuàng)建socket與讀/寫數(shù)據(jù),和服務(wù)端的一模一樣,這里只講一下連接這一步。
函數(shù)原型:
int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
1
第一個參數(shù)為創(chuàng)建的socket文件描述符。
第二個參數(shù)為sockaddr結(jié)構(gòu)體指針,服務(wù)器端的地址信息。
第三個參數(shù)為第二個參數(shù)的長度。
可以使用inet_addr將IP地址從字符串形式轉(zhuǎn)換為二進制形式。
2.2 簡單的客戶端實例:
#include <stdio.h> #include <sys/socket.h> #include <netinet/in.h> #include <string.h>#define PORT 5116 #define BUF_SIZE 256int main(int argc, char** argv) {int fd = socket(AF_INET, SOCK_STREAM, 0);struct sockaddr_in addr;addr.sin_family = AF_INET;addr.sin_port = ntohs(PORT);addr.sin_addr.s_addr = inet_addr("127.0.0.1");int len = sizeof(addr);if (-1 == connect(fd, (struct sockaddr*)&addr, len)){printf("Connect to server fail\n");return 0;}char szMsg[BUF_SIZE];while(scanf("%s", szMsg)){if (!strcmp(szMsg, "quit")){break;}write(fd, szMsg, strlen(szMsg));}close(fd);return 0; }3 一些總結(jié)
在linux中,一切都是文件,所以socket也和普通文件一樣,用文件描述符表示,使用read/write讀寫,使用close關(guān)閉。
對于一般工程而言,服務(wù)端會使用epoll之類的來處理多個客戶端的連接,保證高效正確的運行。
————————————————
版權(quán)聲明:本文為CSDN博主「看熱鬧的咸魚」的原創(chuàng)文章,遵循 CC 4.0 BY-SA 版權(quán)協(xié)議,轉(zhuǎn)載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/lch_boy/article/details/43958861
總結(jié)
以上是生活随笔為你收集整理的Linux下socket编程的简单实例的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 又逢,周末
- 下一篇: ueditor编辑器的使用