基础网络编程——TCP编程

网络编程

实现了一个简单的基于TCP的Windows服务器,它可以简单的执行一次发送数据和一次接收数据

1、TCP 编程

1.1、前期准备
#include <WinSock32.h>					// 包含头文件
#pragma comment(lib, "ws2_32.lib")		// 添加静态链接库

int main() {
    // 网络环境初始化
    WSADATA data;
    WORD virsion = MAKEWORD(2, 2);
    
    int err = WSAStartup(virsion, &data);
    
    if (err != 0)
    {
        printf("WSAStartup errorNum = %d", err);
        return err;
    }
    
    if (LOBYTE(data.wVersion) != 2 || HIBYTE(data.wVersion) != 2)
    {
        printf("LOBYTE errorNum = %d", GetLastError());
        WSACleanup();
        return -1;
    }
    
    WSACleanup();		// 清除网络环境
}

1.2、服务器编程
1.2.1、示例代码
int main() {
    // 一、初始化网络环境
    ....;
    
    // 二、创建服务器
    SOCKET sockSer = socket(AF_INET, SOCK_STREAM, 0);
    
    if (sockSer == INVALID_SOCKET)
    {
        printf("socket errorNum = %d\n", GetLastError());
		return -1;
    }
    
    // 三、分配端口号
    SOCKADDR_IN addrSer;
    addrSer.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
	addrSer.sin_family = AF_INET;		// 始终设置为 AF_INET
	addrSer.sin_port = htons(5201);
    
    if (bind(sockSer, (SOCKADDR*)&addrSer, sizeof(SOCKADDR)) == SOCKET_ERROE)
    {
        printf("bind errorNum = %d\n", GetLastError());
		WSACleanup();
		return -1;
    }
    
    // 四、监听套接字
    if (listen(sockSer, 5) == SOCKET_ERROR)
	{
		printf("listen errorNum = %d\n", GetLastError());
		WSACleanup();
		return -1;
	}
    
    // 五、分机处理
    SOCKADDR_IN addrCli;
    int len = sizeof(SOCKADDR);
    
    while (TRUE)
	{
        // 六、收发数据
		SOCKET sockConn = accept(sockSer, (SOCKADDR*)&addrCli, &len);
		char sendBuff[100] = { 0 };
        ...;		// 将要传输的数据传入sendBuff
		int iLen = send(sockConn, sendBuff, strlen(sendBuff), 0);
        
        if (iLen == SOCKET_ERROR)
        {
            printf("send errorNum = %d\n", GetLastError());
			WSACleanup();
			return -1;
        }
		
		char recvBuff[100] = { 0 };
		iLen = recv(sockConn, recvBuff, 100, 0);
        
        if (iLen <= 0)
        {
            printf("recv errorNum = %d\n", GetLastError());
			WSACleanup();
			return -1;
        }
        printf("recv:%s", recvBuff);
		
		closesocket(sockConn);		// 关闭分机
	}
    
    // 关闭总机
    closesocket(sockSer);
	WSACleanup();
    
    return 0;
}

1.2.2、主要函数
  • 创建服务器套接字:socket()

SOCKET WSAAPI socket(int af, int type, int protocol );

第一个参数为 地址系列规范,使用IPv4 为 AF_INET,使用IPv6为AF_INET6

第二个参数为 套接字的类型规范,地址系列为为IPv4或IPv6的情况下,TCP协议则为SOCK_STREAM,UDP协议为SOCK_DGRAM

第三个参数为 要使用的协议,为 0 则调用方不希望指定协议,服务提供商将选择要使用的 协议

  • 绑定本机 IP 和端口:bind()

int bind(

SOCKET s,                    // 创建的socket

sockaddr * name,          // 包含地址和端口的结构体 int namelen // sockaddr 结构长度

);

// 返回值:返回SOCKET_ERROR失败,该宏被定义为-1,否则成功,返回值为0

  • 监听客户端:listen()

int listen(

SOCKET s,          // 要监听的socket

int backlog           // 等待连接的最大队列长度

);

//返回值:返回SOCKET_ERROR失败,该宏被定义为-1,否则成功,返回值为0

  • 等待客户端连接:accept()

SOCKET accept(

SOCKET s,                   //接收的socket

sockaddr* addr,            //接收到客户端的地址信息

int * addrlen                  //地址信息长度

);

//返回值:返回INVALID_SOCKET失败,该宏定义为-1,否则成功返回客户端的套接字,可进行发送和接收消息

  • 发送信息:send()

  • 接收信息:recv()

int send (

SOCKET s, char * buf, //要发送的内容

int len, //内容长度

int flags //一般为0

);

//返回值:-1(或宏SOCKET_ERROR)表示发送失败,否则返回发送成功的字节数

int recv (

SOCKET s, //套接字

char * buf, //接受数据的缓存区

int len, //缓存区大小

int flags //标志,一般填0

);

//返回值:小于等于0都表示出错,大于0则表示接收成功的数据大小

  • 网络环境初始化:WSAStartup()

  • 关闭 socket :closesocket()

  • 清除网络环境:WSACleanup()

1.3、客户端编程
1.3.1、示例代码
#include <WS2tcpip.h>		// 配置套接字地址新函数的头文件

int main() {
    // 一、初始化网络环境
    ....;
    
    // 二、创建套接字
    SOCKET sockCli = socket(AF_INET, SOCK_STREAM, 0);
    
    if (sockCli == INVALID_SOCKET)
    {
        printf("socket errorNum = %d\n", GetLastError());
		return -1;
    }
    
    // 三、配置要连接的服务器
    SOCKADDR_IN addrCli;
    inet_pton(AF_INET, "客户端的ip地址", &addrCli.sin_addr.S_un.S_addr);
	addrCli.sin_family = AF_INET;
	addrCli.sin_port = htons(5201);
    
    // 四、连接服务器
    if (connect(sockCli, (SOCKADDR*)&addrCli, sizeof(SOCKADDR) == SOCKET_ERROR))
	{
		printf("connect errorNum = %d\n", GetLastError());
		WSACleanup();
		return -1;
	}
    
    // 五、收发数据
    char recvBuff[100] = { 0 };
	int iLen = recv(sockCli, recvBuff, 100, 0);

	if (iLen <= 0)
	{
		printf("recv errorNum = %d\n", GetLastError());
		WSACleanup();
		return -1;
	}
    printf("recv:%s", recvBuff);

	char sendBuff[100] = { 0 };
    ...;			// 写入自己想发送的数据
	iLen = send(sockCli, sendBuff, strlen(sendBuff), 0);
	if (iLen == SOCKET_ERROR)
	{
		printf("send errorNum = %d\n", GetLastError());
		WSACleanup();
		return -1;
	}
    
    // 六、关闭客户机
	closesocket(sockCli);
	WSACleanup();

	system("pause");

	return 0;
}

1.3.2、主要函数

服务器编程中已写过的函数

  • 连接服务器函数:connect()

int connect(

SOCKET s, //与服务器连接的socket

sockaddr* name, //服务器的地址端口

int namelen //上个参数结构体的长度

);

//返回值:-1失败,否则成功

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值