TCP网络通信
windows 平台 TCP 网络通信-服务端流程
- 创建 Socket 套接字.
- Socket 套接字绑定一个端口号.
- Socket 套接字开启监听属性,只能接收连接.
- 等待客户端连接.
- 开始通讯.
- 关闭连接.
代码示例
#include <stdio.h>
#include <string.h>
#include <WinSock2.h>
#include <ws2tcpip.h>
#pragma comment(lib, "ws2_32.lib")
DWORD WINAPI thread_func(LPVOID lpThreadParameter) {
SOCKET client_socket = *(SOCKET*)lpThreadParameter;
free(lpThreadParameter);
// 解决只能发送一条消息的问题.
while (1) {
// 5. 开始通讯
/**
* int recv (
SOCKET s, // 客户端socket
char * buf, // 接收的数据存储
int len, // 接收的长度
int flags // 0
);
*/
char buffer[1024] = { 0 };
int ret = recv(client_socket, buffer, 1024, 0);
if (ret <= 0) break;
printf("%llu: %s\n", client_socket, buffer);
send(client_socket, buffer, (int)strlen(buffer), 0);
}
// 6. 关闭连接
/**
* int closesocket(
SOCKET s
);
*/
printf("socket: %llu, disconnect.\n", client_socket);
closesocket(client_socket);
return 0;
}
int main() {
// windows 端使用网络功能需要开启网络权限
WSADATA wsaData;
// #define MAKEWORD(a, b) ((WORD)(((BYTE)(((DWORD_PTR)(a)) & 0xff)) | ((WORD)((BYTE)(((DWORD_PTR)(b)) & 0xff))) << 8))
// 把两个 BYTE(8 位) 组合成一个 WORD(16 位)
WSAStartup(MAKEWORD(2, 2), &wsaData);
// 1. 创建 socket 套接字
/**
* SOCKET socket(
int af, // 协议地址簇
int type, // 类型 流式协议/帧式协议
int protocol // 保护协议 0
);
*/
SOCKET listen_socket = socket(AF_INET, SOCK_STREAM, 0);
if (INVALID_SOCKET == listen_socket) {
printf("create listen socket failed !!! errcode: %d\n", GetLastError());
return -1;
}
// 2. 给这个 socket 套接字绑定一个端口号
/**
* typedef struct sockaddr_in {
short sin_family; // 协议地址簇 IPV4/IPV6 AF_INET/AF_INET6
USHORT sin_port; // 端口号
IN_ADDR sin_addr; // IP地址
CHAR sin_zero[8]; // 保留字节
};
*/
struct sockaddr_in local = { 0 };
local.sin_family = AF_INET;
// 8080对应16进制:1F90.
// 大端序模式:高位在前,低位在后. (千百十个,正常的阅读顺序).
// 小端模式: 低位在前,高位在后. (本地PC电脑以小端序存储数据).
// htons: short类型
local.sin_port = htons(8080); // 大小端问题
// htol: long类型.
// INADDR_ANY: 监听所有网卡的该端口.
//local.sin_addr.s_addr = htonl(INADDR_ANY); // 服务端, 只接受哪个网卡的数据.
// inet_addr(废弃的API): 字符串IP地址转化为整数IP地址.
// 如果使用 inet_addr,需要加 #define _WINSOCK_DEPRECATED_NO_WARNINGS .
//local.sin_addr.s_addr = inet_addr("0.0.0.0");
InetPton(AF_INET, TEXT("0.0.0.0"), &local.sin_addr);
/**
* int bind(
SOCKET s,
const struct sockaddr * name,
int namelen
)
*/
if (-1 == bind(listen_socket, (struct sockaddr*)&local, sizeof(local))) {
printf("bind socket failed !!! errcode: %d\n", GetLastError());
return -1;
}
// 3. 给这个socket 开启监听属性
/**
* int listen(
SOCKET s,
int backlog
);
*/
if (-1 == listen(listen_socket, 10)) {
printf("start listen socket failed !!! errcode: %d\n", GetLastError());
return -1;
}
// 4. 等待客户端连接
/**
* SOCKET accept(
SOCKET s, // 监听socket
struct sockaddr * addr, // 客户端的IP地址和端口号
int * addrlen // 结构大小
);
*/
// client_socket: 通讯 Socket,服务端与客户端通过该 socket 通信.
while (1) {
SOCKET client_socket = accept(listen_socket, NULL, NULL);
if (INVALID_SOCKET == client_socket) {
continue;
}
printf("new connect.socket:%llu\n", client_socket);
SOCKET* sockfd = (SOCKET*)malloc(sizeof(SOCKET));
*sockfd = client_socket;
// 创建线程, 解决只能和一个客户端通讯的问题.
CreateThread(NULL, 0, thread_func, sockfd, 0, NULL);
}
}
windows 平台 TCP 网络通信-客户端流程
- 创建 socket 套接字.
- 连接服务器.
- 开始通讯.
- 关闭连接.
代码示例
#include <stdio.h>
#include <WinSock2.h>
#include <ws2tcpip.h>
#pragma comment(lib, "ws2_32.lib")
int main() {
WSADATA wsaData;
WSAStartup(MAKEWORD(2, 2), &wsaData);
// 1. 创建 socket 套接字
SOCKET client_socket = socket(AF_INET, SOCK_STREAM, 0);
if (INVALID_SOCKET == client_socket) {
printf("create socket failed !!!\n");
return -1;
}
// 2. 连接服务器
struct sockaddr_in target;
target.sin_family = AF_INET;
target.sin_port = htons(8080);
//target.sin_addr.s_addr = inet_addr("127.0.0.1");
InetPton(AF_INET, TEXT("127.0.0.1"), &target.sin_addr);
if (-1 == connect(client_socket, (struct sockaddr*)&target, sizeof(target))) {
printf("connect server failed !!!\n");
closesocket(client_socket);
return -1;
}
// 3. 开始通讯
while (1) {
char sbuffer[1024] = { 0 };
printf("Please enter: ");
// 使用 scanf 不安全,需要加 #define _CRT_SECURE_NO_WARNINGS 关闭警告.
//scanf("%s", sbuffer);
scanf_s("%99s", sbuffer, (unsigned)_countof(sbuffer));
send(client_socket, sbuffer, strlen(sbuffer), 0);
char rbuffer[1024] = { 0 };
int ret = recv(client_socket, rbuffer, 1024, 0);
if (ret <= 0) {
break;
}
printf("%s\n", rbuffer);
}
// 4. 关闭连接
closesocket(client_socket);
return 0;
}