A Simple Socket Application

因为我的毕业设计要用到网络,一开始我就打算做 IOCP Server,我想用最好的方法去实现,结果发现啃不动,于是就从这个示例程序开始吧!

客户端代码:

/*
 * 文件:简单示例(客户端)
 * 说明:项目中需包含 Ws2_32.lib,或使用 #pragma once
 */

#include <stdio.h>
#include <WinSock2.h>

#define LENGTH 128
#define PORT_NUM 8086
#define EXIT_WITH_MESSAGE(content) \
do \
{ \
	WSACleanup(); \
	printf_s(content); \
	system("pause"); \
	return EXIT_FAILURE; \
} \
while (FALSE);

int main()
{
	int ret, len;
	WORD wVersion;							// 网络传输版本
	WSADATA wsaData;						// WSADATA
	char msg[LENGTH];
	struct sockaddr_in server;				// 服务器信息
	SOCKET sockClient = INVALID_SOCKET;		// 待创建的套接字

	wVersion = MAKEWORD(2, 2);
	ret = WSAStartup(wVersion, &wsaData);	// 初始化 WinSock DLL
	if (ret != 0)
	{
		// 告诉用户不能获取可用的 WinSock DLL
		EXIT_WITH_MESSAGE("WSAStartup Failed, cannot find a usable winsock dll!\n");
	}

	if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2)
	{
		// 告诉用户版本不正确
		EXIT_WITH_MESSAGE("Error version!\n");
	}

	sockClient = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
	if (INVALID_SOCKET == sockClient)
	{
		// 套接字创建失败
		EXIT_WITH_MESSAGE("Invalid socket!\n");
	}

	server.sin_family = AF_INET;
	server.sin_port = htons(PORT_NUM);
	server.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");

	ret = connect(sockClient, (struct sockaddr *)&server, sizeof(struct sockaddr));
	if (SOCKET_ERROR == ret)
	{
		// 连接失败
		closesocket(sockClient);
		EXIT_WITH_MESSAGE("Connect failed!\n");
	}

	do
	{
		printf_s("Input a message to send (Note: Length < 128): ");
		gets_s(msg, LENGTH);
		// send 函数将会把消息发送到已连接的套接字上,而 sendto 则是发送到指定套接字上
		len = strlen(msg) + 1;
		ret = send(sockClient, msg, len, 0);
		if (ret < 0 || ret > len)
		{
			// 发送有误
			closesocket(sockClient);
			EXIT_WITH_MESSAGE("Send message error!\n");
		}

		if (strcmp(msg, "Quit") == 0)
			break;

		memset(msg, 0, LENGTH);
		ret = recv(sockClient, msg, LENGTH, 0);
		if (SOCKET_ERROR == ret)
		{
			// 接受有误
			closesocket(sockClient);
			EXIT_WITH_MESSAGE("Receive message error!\n");
		}
		else if (0 == ret)
		{
			// 连接断开
			closesocket(sockClient);
			EXIT_WITH_MESSAGE("The connection closed!\n");
		}

		printf_s("Client reply: %s\n", msg);
	}
	while (strcmp(msg, "Quit"));

	printf_s("Exit connection!\n");
	closesocket(sockClient);
	WSACleanup();
	system("pause");

	return EXIT_SUCCESS;
}


 

服务器端代码:

/*
 * 文件:简单示例(服务器端)
 * 说明:项目中需包含 Ws2_32.lib,或使用 #pragma once
 */

#include <stdio.h>
#include <WinSock2.h>

#define LENGTH 128
#define PORT_NUM 8086
#define EXIT_WITH_MESSAGE(content) \
do \
{ \
	WSACleanup(); \
	printf_s(content); \
	system("pause"); \
	return EXIT_FAILURE; \
} \
while (FALSE);

int main()
{
	int ret, len;
	WORD wVersion;														// 网络传输版本
	WSADATA wsaData;													// WSADATA
	char msg[LENGTH];
	struct sockaddr_in server, client;									// 服务器信息,客户端信息
	SOCKET sockServer = INVALID_SOCKET, sockListener = INVALID_SOCKET;	// 服务器套接字,监听套接字

	wVersion = MAKEWORD(2, 2);
	ret = WSAStartup(wVersion, &wsaData);	// 初始化 WinSock DLL
	if (ret != 0)
	{
		// 告诉用户不能获取可用的 WinSock DLL
		EXIT_WITH_MESSAGE("WSAStartup Failed, cannot find a usable winsock dll!\n");
	}

	if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2)
	{
		// 告诉用户版本不正确
		EXIT_WITH_MESSAGE("Error version!\n");
	}

	sockListener = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
	if (INVALID_SOCKET == sockListener)
	{
		// 套接字创建失败
		EXIT_WITH_MESSAGE("Invalid listener socket!\n");
	}

	server.sin_family = AF_INET;
	server.sin_addr.s_addr = INADDR_ANY;
	server.sin_port = htons(PORT_NUM);

	ret = bind(sockListener, (struct sockaddr *)&server, sizeof(struct sockaddr_in));
	if (SOCKET_ERROR == ret)
	{
		// 绑定端口失败
		closesocket(sockListener);
		EXIT_WITH_MESSAGE("Bind error!\n");
	}

	ret = listen(sockListener, SOMAXCONN);
	if (SOCKET_ERROR == ret)
	{
		// 监听失败
		closesocket(sockListener);
		EXIT_WITH_MESSAGE("Listen error!\n");
	}

	len = sizeof(struct sockaddr_in);
	sockServer = accept(sockListener, (struct sockaddr*)&client, &len);
	if (INVALID_SOCKET == sockServer)
	{
		// 接收失败
		closesocket(sockListener);
		EXIT_WITH_MESSAGE("Accept error!\n");
	}

	do
	{
		memset(msg, 0, LENGTH);
		ret = recv(sockServer, msg, LENGTH, 0);
		if (SOCKET_ERROR == ret)
		{
			// 接受有误
			closesocket(sockServer);
			EXIT_WITH_MESSAGE("Receive message error!\n");
		}
		else if (0 == ret)
		{
			// 连接断开
			closesocket(sockServer);
			EXIT_WITH_MESSAGE("The connection closed!\n");
		}
		printf_s("Client: %s\n", msg);

		strcpy_s(msg, LENGTH, "SweetLover has received your letter, he'll reply soon!");
		len = strlen(msg) + 1;
		ret = send(sockServer, msg, len, 0);
		if (ret <= 0 || ret > len)
		{
			// 发送有误
			closesocket(sockServer);
			EXIT_WITH_MESSAGE("Send message error!\n");
		}
	}
	while (TRUE);

	printf_s("Exit connection!\n");
	closesocket(sockServer);
	closesocket(sockListener);
	WSACleanup();
	system("pause");

	return EXIT_SUCCESS;
}


总结:

1.网络连接的步骤:http://blog.csdn.net/wwqingyue/article/details/8792608

UDP和TCP编程步骤也有些不同,如下: 

  TCP编程的服务器端一般步骤是: 

  1、创建一个socket,用函数socket();
  2、设置socket属性,用函数setsockopt(); * 可选
  3、绑定IP地址、端口等信息到socket上,用函数bind();
  4、开启监听,用函数listen();
  5、接收客户端上来的连接,用函数accept();
  6、收发数据,用函数send()和recv(),或者read()和write();
  7、关闭网络连接;
  8、关闭监听;

 

  TCP编程的客户端一般步骤是: 

  1、创建一个socket,用函数socket();
  2、设置socket属性,用函数setsockopt();* 可选
  3、绑定IP地址、端口等信息到socket上,用函数bind();* 可选
  4、设置要连接的对方的IP地址和端口等属性;
  5、连接服务器,用函数connect();
  6、收发数据,用函数send()和recv(),或者read()和write();
  7、关闭网络连接;

 

  与之对应的UDP编程步骤要简单许多,分别如下: 

  UDP编程的服务器端一般步骤是: 

  1、创建一个socket,用函数socket();
  2、设置socket属性,用函数setsockopt();* 可选
  3、绑定IP地址、端口等信息到socket上,用函数bind();
  4、循环接收数据,用函数recvfrom();
  5、关闭网络连接;

 

  UDP编程的客户端一般步骤是: 

  1、创建一个socket,用函数socket();
  2、设置socket属性,用函数setsockopt();* 可选
  3、绑定IP地址、端口等信息到socket上,用函数bind();* 可选
  4、设置对方的IP地址和端口等属性;
  5、发送数据,用函数sendto();
  6、关闭网络连接;

2.套接字编程原理:http://www.cnblogs.com/haoyuanyuan/p/3268351.html

3.常用术语概念:http://www.vckbase.com/index.php/wv/300

socket 通信关于bind那点事

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值