socket套接字函数接口参数:
1.SOCKET sock = socket(int af, int type, int protocol);
(1)af 为地址族(Address Family),IP 地址类型,常用的有 AF_INET 和 AF_INET6。AF_INET 表示 IPv4 地址,例如 127.0.0.1;AF_INET6 表示 IPv6 地址,例如 1030::C9B4:FF12:48AA:1A2B。
**注意:127.0.0.1,它是一个特殊IP地址,表示本机地址
(2)type 为数据传输方式/套接字类型,常用的有 SOCK_STREAM(流格式套接字/面向连接的套接字) 和 SOCK_DGRAM(数据报套接字/无连接的套接字)。
(3)protocol 表示传输协议,常用的有 IPPROTO_TCP 和 IPPTOTO_UDP,分别表示 TCP 传输协议和 UDP 传输协议。
2.int bind(SOCKET sock, const struct sockaddr *addr, int addrlen);
(1)sock 为 socket 文件描述符。
(2)addr 为 sockaddr 结构体变量的指针。
(3)addrlen 为 addr 变量的大小,可由 sizeof() 计算得出。
使用struct sockaddr_in结构体:
struct sockaddr_in{
sa_family_t sin_family; //地址族(Address Family),也就是地址类型
uint16_t sin_port; //16位的端口号
struct in_addr sin_addr; //32位IP地址
char sin_zero[8]; //不使用,一般用0填充
};
struct in_addr{
in_addr_t s_addr; //32位的IP地址
};
3.int connect(SOCKET sock, const struct sockaddr *serv_addr, int addrlen); 与bind类似
4.int listen(SOCKET sock, int backlog);
//被动监听,是指当没有客户端请求时,套接字处于“睡眠”状态,只有当接收到客户端请求时,套接字才会被“唤醒”来响应请求。
sock 为需要进入监听状态的套接字,backlog 为请求队列的最大长度。
5.SOCKET accept(SOCKET sock, struct sockaddr *addr, int *addrlen);
当套接字处于监听状态时,可以通过 accept() 函数来接收客户端请求。
accept() 返回一个新的套接字来和客户端通信,addr 保存了客户端的IP地址和端口号,而 sock 是服务器端的套接字,大家注意区分。后面和客户端通信时,要使用这个新生成的套接字。
注意:listen() 只是让套接字进入监听状态,并没有真正接收客户端请求,listen() 后面的代码会继续执行,直到遇到 accept()。
accept() 会阻塞程序执行(后面代码不能被执行),直到有新的请求到来。
6.int send(SOCKET sock, const char *buf, int len, int flags);
sock 为要发送数据的套接字,buf 为要发送的数据的缓冲区地址,len 为要发送的数据的字节数,flags 为发送数据时的选项
7.int recv(SOCKET sock, char *buf, int len, int flags);
server
// Sock01.cpp : 定义控制台应用程序的入口点。
//
//#define _WINSOCK_DEPRECATED_NO_WARNINGS //属性 预处理 添加
#include "stdafx.h"
#include<WinSock2.h>
#include<Windows.h>
//#pragma comment(lib,"ws2_32.lib")
int main()
{
WORD ver = MAKEWORD(2, 2);
WSADATA dat;
WSAStartup(ver, &dat); //启动windows socket 2环境
//建立简易的tcp服务端
//1
SOCKET _sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); //socket编程有三种:流式套接字(SOCK_STREAM),数据报套接字(SOCK_DGRAM),原始套接字(SOCK_RAW) TCP基于流式
//2.BIND 绑定用于接受客户端连接的网络端口
sockaddr_in _sin = {};
_sin.sin_family = AF_INET;
_sin.sin_port = htons(4567);// host to net unsigned short
_sin.sin_addr.S_un.S_addr = INADDR_ANY;
if (SOCKET_ERROR == bind(_sock, (sockaddr*)&_sin, sizeof(_sin)))
{
printf("错误,绑定失败\n");
}
else
{
printf("绑定成功\n");
}
//3.listen 监听网络端口
if (SOCKET_ERROR == listen(_sock, 5))
{
printf("错误,监听失败\n");
}
else
{
printf("监听成功\n");
}
//4.accept 等待接收客户端连接
sockaddr_in clientAddr = {};
int nDddrLen = sizeof(sockaddr_in);
SOCKET _cSock = INVALID_SOCKET;
_cSock = accept(_sock, (sockaddr*)&clientAddr, &nDddrLen);
if (_cSock == INVALID_SOCKET)
{
printf("错误,接受到无效客户端socke..\n");
}
printf("新客户端加入:socket = %d, IP = %s\n",_cSock, inet_ntoa(clientAddr.sin_addr));
char _recvBuf[256] = {}; //接收数据
while (true)
{
//5.接收客户端请求数据
int nLen = recv(_cSock,_recvBuf,256,0);
if (nLen<=0)
{
printf("客户端已退出,任务结束\n");
break;
}
printf("收到命令:%s\n",_recvBuf);
//6.处理请求
if (0 == strcmp(_recvBuf,"getName"))
{
//7.send 向客户端发送一条数据
char msgBuf[] = "Server0102\n";
send(_cSock, msgBuf, strlen(msgBuf) + 1, 0);
}
else if (0 == strcmp(_recvBuf, "getAge"))
{
//7.send 向客户端发送一条数据
char msgBuf[] = "23\n";
send(_cSock, msgBuf, strlen(msgBuf) + 1, 0);
}
else
{
//7.send 向客户端发送一条数据
char msgBuf[] = "?????\n";
send(_cSock, msgBuf, strlen(msgBuf) + 1, 0);
}
}
//6.关闭套接字socket
closesocket(_cSock);
WSACleanup();
printf("已退出,任务结束\n");
getchar();
return 0;
}
Client
// Client.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include<WinSock2.h>
#include<Windows.h>
//#pragma comment(lib,"ws2_32.lib")
#include<iostream>
using namespace std;
int main()
{
WORD ver = MAKEWORD(2, 2);
WSADATA dat;
WSAStartup(ver, &dat); //启动windows socket 2环境
//建立简易的tcp服务端
//1.建立一个socket
SOCKET _sock = socket(AF_INET,SOCK_STREAM,0);
if (INVALID_SOCKET == _sock)
{
printf("错误,建立client socket失败。。\n");
}
else
{
printf("建立client socket成功\n");
}
//2.连接服务器
sockaddr_in _sin = {};
_sin.sin_family = AF_INET;
_sin.sin_port = htons(4567);
_sin.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
int ret = connect(_sock,(sockaddr*)&_sin,sizeof(sockaddr_in));
if (SOCKET_ERROR == ret)
{
printf("错误,连接socket失败。。\n");
}
else
{
printf("连接socket成功\n");
}
while (true)
{
//3.输入请求命令
char cmdBuf[256] = {};
scanf("%s", cmdBuf);
//4.处理数据请求
if (0 == strcmp(cmdBuf,"exit"))
{
printf("收到退出命令,任务结束\n");
break;
}
else
{
//5.向服务器发送请求命令
send(_sock,cmdBuf,strlen(cmdBuf)+1,0);
}
//6.接受服务信息 recv
char recvBuf[256] = {};
int nlen = recv(_sock, recvBuf, 256, 0);
if (nlen > 0)
{
printf("接收到的收据:%s\n", recvBuf);
}
}
//7.结束套接字
closesocket(_sock);
WSACleanup();
printf("退出命令,任务结束\n");
getchar();
return 0;
}