参考:
Linux之本地Socket通信
Linux Socket过程详细解释(包括三次握手建立连接,四次握手断开连接)
Linux socket 本地进程间通信
最近笔试遇到一个选择题,说在Linux进行Socket通信的时候那个阶段不会阻塞。由于没有接触过这方面的内容,通过查找一些资料进行学习。
socket起源于Unix,而Unix/Linux基本哲学之一就是“一切皆文件”,都可以用“打开open –> 读写write/read –> 关闭close”模式来操作。Socket就是该模式的一个实现, socket即是一种特殊的文件,一些socket函数就是对其进行的操作(读/写IO、打开、关闭).
Socket是应用层与TCP/IP协议族通信的中间软件抽象层,它是一组接口。它把复杂的TCP/IP协议隐藏在Socket接口后,对用户来说一组简单的接口就是全部,让Socket去组织数据,以符合指定的协议。
Socket通信流程
服务器端需要创建Socket,绑定地址,进行监听。
客户端需要创建Socket,建立连接(指定地址),然后进行数据交互。
流程图如下:

C++的连接用send发送数据,recv接收数据。
Socket 服务端例子
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78
| #include <stdio.h> #include <winsock2.h>
int main() { WORD sockVersion = MAKEWORD(2, 2); WSADATA wsaData; if (WSAStartup(sockVersion, &wsaData) != 0) { return 0; }
SOCKET slisten = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (slisten == INVALID_SOCKET) { printf("socket error!"); return -1; } sockaddr_in sin; sin.sin_family = AF_INET; sin.sin_port = htons(8888); sin.sin_addr.S_un.S_addr = INADDR_ANY;
if (bind(slisten, (LPSOCKADDR)&sin, sizeof(sin)) == SOCKET_ERROR) { printf("bind error!"); } if (listen(slisten, 5) == SOCKET_ERROR) { printf("listen error!"); } SOCKET sClient; sockaddr_in remoteAddr; int nAddrlen = sizeof(remoteAddr); char revData[255]; while (true) { printf("\nWaiting for connect...\n"); sClient = accept(slisten, (SOCKADDR *)&remoteAddr, &nAddrlen); if (sClient == INVALID_SOCKET) { printf("accept error !"); continue; } printf("\nACCEPT an connection: %s \r\n", inet_ntoa(remoteAddr.sin_addr));
int ret = recv(sClient, revData, 255, 0); if (ret > 0) { revData[ret] = 0x00; printf(revData); } const char *sendData = "\nHello,TCP clinet!\n"; send(sClient, sendData, strlen(sendData), 0); closesocket(sClient); } closesocket(slisten); WSACleanup(); return 0; }
|
Socket 客户端连接例子
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61
| #include <WINSOCK2.H> #include <STDIO.H> #include <iostream> #include <cstring> #include <string> using namespace std; #pragma comment(lib, "ws2_32.lib")
int main() { WORD sockVersion = MAKEWORD(2, 2); WSADATA data; if (WSAStartup(sockVersion, &data) != 0) { return 0; } while (true) { SOCKET sclient = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (sclient == INVALID_SOCKET) { printf("invalid socket!"); return 0; } sockaddr_in serAddr; serAddr.sin_family = AF_INET; serAddr.sin_port = htons(8888); serAddr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1"); if (connect(sclient, (sockaddr *)&serAddr, sizeof(serAddr)) == SOCKET_ERROR) { printf("connect error !"); closesocket(sclient); return 0; }
string data; std::cin >> data; const char *sendData; sendData = data.c_str(); send(sclient, sendData, strlen(sendData), 0);
char recData[255]; int ret = recv(sclient, recData, 255, 0); if (ret > 0) { recData[ret] = 0x00; printf(recData); } closesocket(sclient); }
WSACleanup(); return 0; }
|