分成两个项目:服务端和客户端,完整源码在最后
服务端
包含相关的库文件
1
2
3开启网络权限
1
2WSADATA wsaData;
WSAStartup(MAKEWORD(2, 2), &wsaData);创建socket套接字
先看一下socket的数据结构
1
2
3
4
5socket(
_In_ int af, //协议地址族 AF_INET/AF_INET6 ipv4/ipv6
_In_ int type, //协议类型 TCP/UDP SOCK_STREAM/SOCK_DGRAM
_In_ int protocol //保护方式
);创建socket,如果创建失败,socket值为-1
1
2
3
4
5
6
7//创建socket
SOCKET server_socket = socket(AF_INET, SOCK_STREAM, 0);//如果创建失败为-1
//进行检查
if (server_socket == -1) {
printf("server socket create failed!Error Code:%d\n", GetLastError());
exit(-1);
}指定ip和端口号
先来看一下
struct sockaddr_in
的数据结构1
2
3
4
5
6
7typedef struct sockaddr_in {
short sin_family;//协议地址族
USHORT sin_port;//端口号 5000+
IN_ADDR sin_addr;//服务端,所有网卡都要监测,所以一般为0.0.0.0
//inet_addr()——将点分十进制的IP地址转换为整数
CHAR sin_zero[8];//保留位置 可能将来升级协议可能会用
} SOCKADDR_IN, * PSOCKADDR_IN;这里涉及到大端序和小端序的内容
大端序:数字大的在前面 比如:百 十 个
小端序:数字小的在前面 比如:个 十 百
例:本地为
90 1f 00 00
为小端序,网络上为大端序00 00 1f 90
(实际值)——8080htons()
:小端序转换为大端序 eg:htons(8080);
1
2
3
4struct sockaddr_in local;
local.sin_family = AF_INET;
local.sin_port = htons(8080);//将8080转换为大端序
local.sin_addr.S_un.S_addr = inet_addr("0.0.0.0");绑定socket和端口
bind()
1
2
3
4
5
6// 绑定socket和端口
if (bind(server_socket, (struct sockaddr*)&local, sizeof(struct sockaddr_in))
== -1) {
printf("bind server socket failed!Error Code:%ld\n", GetLastError());
exit(-1);
}监听端口
listen()
1
2
3
4
5if (listen(server_socket, 10) == -1) {
printf("listen server socket failed!Error Code:%ld\n", GetLastError());
exit(-1);
}
printf("bind and listen success. wait client connect ...\n");等待客户端连接
accept()
:函数进行过程就是三次握手accept函数是阻塞函数,没有客户端连接就停在这里
server_socket
:负责传话返回值:一个新的socket负责通信
1
SOCKET client_socket = accept(server_socket, NULL, NULL);
循环处理
可以接收消息或者发送消息,在循环内部自行定义
recv()
:从通信socket上接收数据- 返回值为-1,表示出错
- 返回值为0,表示正常断开
- 返回值为正数,表示接收到了多少数据
1
2
3
4
5
6
7
8
9
10
11
12
13while (1) {
char buff[BUFSIZ * 4] = { 0 };//接收数据
int ret = recv(client_socket, buff, BUFSIZ * 4, 0);
if (ret <= 0) break;
printf("ret:%d buff:%s\n", ret, buff);
if (memcmp(buff, "music", strlen("music")) == 0) {
//表示当你接收到"music",进行这部分处理
printf("playing music\r\n");
}
}
客户端
包含相关的库文件
1
2
3开启网络权限
1
2WSADATA wsaData;
WSAStartup(MAKEWORD(2, 2), &wsaData);创建socket套接字
跟服务端代码一样
1
2
3
4
5
6//创建socket
SOCKET client_socket = socket(AF_INET, SOCK_STREAM, 0);
if (client_socket == -1) {
printf("client socket create failed!Error Code:%d\n", GetLastError());
exit(-1);
}指定目标ip和端口号
跟服务端不同的是,不是监听所有,只是针对目标ip
1
2
3
4
5
6struct sockaddr_in target;
target.sin_family = AF_INET;
target.sin_port = htons(8080);
//127.0.0.1本地环回
//或者填本机ip
target.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");直接连接就行
connect()
1
2
3
4//直接连接就行
if (connect(client_socket, (struct sockaddr*)&target, sizeof(struct sockaddr)) == -1) {
printf("connect server failed!Error Code:%ld\n",GetLastError());
}进行通信
1
2
3
4
5
6
7
8while (1) {
char buff[BUFSIZ * 4] = { 0 };
printf("please input send content:");
scanf("%s",buff);
int ret = send(client_socket, buff, strlen(buff), 0);
if (ret <= 0)
break;
}
最后同时运行两个项目就可以了!
完整源码
服务端
1 |
|
客户端
1 |
|