Linux下使用使用socket實(shí)現(xiàn)TCP服務(wù)端的示例代碼
套接字(socket)是 Linux 下的一種進(jìn)程間通信機(jī)制(socket IPC),它不僅支持同一主機(jī)的不同進(jìn)程間通信,還支持跨網(wǎng)絡(luò)的不同主機(jī)的進(jìn)程間通信。
socket 允許通過(guò)標(biāo)準(zhǔn)的文件描述符進(jìn)行網(wǎng)絡(luò)數(shù)據(jù)傳輸,支持各種網(wǎng)絡(luò)協(xié)議,如 TCP 和 UDP,它把復(fù)雜的 TCP/IP 協(xié)議隱藏在 socket 接口下,對(duì)用戶來(lái)說(shuō),一組簡(jiǎn)單的接口就是全部,讓 socket 去組織數(shù)據(jù),以符合指定的協(xié)議。
基于 socket 接口編寫(xiě)的應(yīng)用程序可以移植到任何實(shí)現(xiàn) BSD socket 標(biāo)準(zhǔn)的平臺(tái)。本文介紹了 Linux 下使用 socket 接口實(shí)現(xiàn) TCP 服務(wù)端的示例程序。
- 開(kāi)發(fā)環(huán)境:虛擬機(jī) Ubuntu 18.04
- 驗(yàn)證平臺(tái):Elfboard Linux 開(kāi)發(fā)板
- 客戶端:Windows 網(wǎng)絡(luò)調(diào)試助手 NetAssist
示例代碼
- tcp_server.c
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <arpa/inet.h> #include <sys/socket.h> #include <netinet/in.h> #include <netinet/tcp.h> #include <errno.h> #include "tcp_server.h" int server_init_socket(void) { int socket_fd; struct sockaddr_in address; if ((socket_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0) { perror("socket failed"); exit(EXIT_FAILURE); } address.sin_family = AF_INET; address.sin_addr.s_addr = INADDR_ANY; address.sin_port = htons(PORT); if (bind(socket_fd, (struct sockaddr *)&address, sizeof(address)) < 0) { perror("bind failed"); exit(EXIT_FAILURE); } if (listen(socket_fd, 3) < 0) { perror("listen"); exit(EXIT_FAILURE); } return socket_fd; } int server_set_socket_timeout(int socket_fd, long milliseconds) { struct timeval tv; tv.tv_sec = milliseconds / 1000; tv.tv_usec = (milliseconds % 1000) * 1000; if (setsockopt(socket_fd, SOL_SOCKET, SO_RCVTIMEO, (const char*)&tv, sizeof(tv)) < 0) { perror("setsockopt SO_RCVTIMEO"); exit(EXIT_FAILURE); } return 0; } int server_accept_client(int socket_fd) { struct sockaddr_in address; int addrlen = sizeof(address); int temp_fd = accept(socket_fd, (struct sockaddr *)&address, (socklen_t*)&addrlen); if (temp_fd < 0) { perror("accept"); exit(EXIT_FAILURE); } printf("Connection established with %s:%d\n", inet_ntoa(address.sin_addr), ntohs(address.sin_port)); return temp_fd; } int server_receive_data(int socket_fd, char *message, ssize_t *size) { ssize_t bytes_received = recv(socket_fd, message, BUFFER_SIZE, 0); if (bytes_received == -1) { if (errno == EAGAIN || errno == EWOULDBLOCK || errno == ETIMEDOUT) { printf("socket recv time out \r\n"); return 1; } else { perror("recv"); exit(EXIT_FAILURE); } } *size = bytes_received; return 0; } void server_send_data(int socket_fd, const char *message, ssize_t size) { if (send(socket_fd, message, size, 0) < 0) { perror("send"); exit(EXIT_FAILURE); } } int server_check_tcp_connection(int socket_fd) { int error = 0; socklen_t len = sizeof(error); if (getsockopt(socket_fd, SOL_SOCKET, SO_ERROR, &error, &len) == 0) { if (error == 0) { return 1; } } return 0; } int server_close_socket(int socket_fd) { close(socket_fd); return 0; }
- tcp_server.h
#ifndef __TCP_SERVER__ #define __TCP_SERVER__ #include <sys/socket.h> #define PORT 8080 #define BUFFER_SIZE 1024 int server_init_socket(void); int server_accept_client(int socket_fd); int server_set_socket_timeout(int socket_fd, long milliseconds); int server_receive_data(int socket_fd, char *message, ssize_t *size) ; void server_send_data(int socket_fd, const char *message, ssize_t size); int server_check_tcp_connection(int socket_fd); int server_close_socket(int fd); #endif
- main.c
#include <stdio.h> #include "tcp_server.h" int main(void) { int server_fd, client_fd; char buffer[1024] = {0}; ssize_t size = 0; server_fd = server_init_socket(); client_fd = server_accept_client(server_fd); server_send_data(client_fd, "Hello Client!", 13); server_receive_data(client_fd, buffer, &size); printf("%s", buffer); server_close_socket(client_fd); server_close_socket(server_fd); return 0; }
- 通過(guò)交叉編譯生成目標(biāo)程序,拷貝到 Elfboard Linux 開(kāi)發(fā)板上
板級(jí)驗(yàn)證
- 啟動(dòng) Elfboard Linux 開(kāi)發(fā)板作為服務(wù)端,查看 IP:
- 打開(kāi)網(wǎng)絡(luò)調(diào)試助手,配置協(xié)議類(lèi)型為 TCP 客戶端,設(shè)置服務(wù)端 IP、端口號(hào):
- 運(yùn)行服務(wù)端程序,等待客戶端連接:
- 客戶端點(diǎn)擊連接:
- 服務(wù)端顯示客戶端已連接:
- 客戶端收到服務(wù)端發(fā)送的消息:
- 客戶端回復(fù)服務(wù)端消息:
- 服務(wù)端接收到客戶端消息:
以上就是Linux下使用使用socket實(shí)現(xiàn)TCP服務(wù)端的示例代碼的詳細(xì)內(nèi)容,更多關(guān)于Linux socket實(shí)現(xiàn)TCP服務(wù)端的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Linux利用Shell腳本部署jar包項(xiàng)目的完整步驟
這篇文章主要給大家介紹了關(guān)于Linux如何利用Shell腳本部署jar包項(xiàng)目的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-12-12linux網(wǎng)絡(luò)參數(shù)配置方法詳解
這篇文章主要介紹了linux網(wǎng)絡(luò)參數(shù)的配置方法,這樣可以讓你的服務(wù)器訪問(wèn)網(wǎng)絡(luò),主要參數(shù):IP地址、子網(wǎng)掩碼、網(wǎng)關(guān)、DNS2013-11-11Linux命令之fdisk磁盤(pán)分區(qū)工具使用
這篇文章主要介紹了Linux命令之fdisk磁盤(pán)分區(qū)工具使用,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-08-08Linux實(shí)現(xiàn)雙網(wǎng)卡綁定的代碼詳解
linux 主機(jī)安裝雙網(wǎng)卡,共享一個(gè)IP地址,對(duì)外提供訪問(wèn),實(shí)際同樣連接兩條物理線路到交換機(jī)實(shí)現(xiàn)平時(shí)雙網(wǎng)卡同時(shí)工作,分流網(wǎng)絡(luò)壓力,同時(shí)提供冗余備份,監(jiān)控,防止物理線路的單點(diǎn)故障,本文介紹了Linux實(shí)現(xiàn)雙網(wǎng)卡綁定的代碼示例,需要的朋友可以參考下2024-07-07