socket编程

 一、基于TCP的socket编程

服务器端程序:

1)创建套接字(socket)。

此系统调用的实际效果是,请求操作系统把网络通信所需要的一些系统资源(存储器空间、CPU时间、网络宽带等)分配给该应用进程。

2)将套接字绑定到一个本地地址和端口上(bind)。

3)将套接字设为监听模式,准备接收客户请求(listen)。

4)等待客户请求到来;当请求到来后,接受连接请求,返回一个新的对应于此次连接的套接字(accept)。

5)用返回的套接字和客户端进行通信(send/recv)。

6)返回,等待另一客户请求。

7)关闭套接字(closesocket)。

此系统调用,通知操作系统回收与该套接字描述符相关的所有资源。

客户端程序:

1)创建套接字(socket)。

2)向服务器发出连接请求(connect)。

3)和服务器端进行通信(send/recv)。

4)关闭套接字(closesocket)。

二、基于UDP的socket编程

服务器端(接收端)程序:

1)创建套接字(socket)。

2)将套接字绑定到一个本地地址和端口上(bind)。

3)等待接收数据(recvfrom)。

4)关闭套接字(closesocket)。

客户端(发送端)程序:

1)创建套接字(socket)。

2)向服务器发送数据(sendto)。

3)关闭套接字(closesocket)。

 三、相关函数   

1)int WSAStartup(WORD wVersionRequested, LPWSADATA lpWSAData); //启动进程使用ws2.dll

wVersionRequested参数:用于指定准备加载的Winsock库的版本。高位字节指定所需要的Winsock库的副版本,而低位字节则是主版本。可用MAKEWORD(x, y);(其中,x是高位字节,y是低位字节)方便地获得wVersionRequested的正确值。

 lpWSAData参数:指向WSADATA结构的指针,WSAStartup用其加载的库版本有关的信息填在这个结构中。

2)SOCKET socket(int af, int type, int protocol); //创建与特定服务提供者绑定的套接字

af参数:指定地址族,对于TCP/IP协议的套接字,它只能是AF_INET(也可写成PF_INET)。

type参数:指定Socket类型,对于1.1版本的Socket,它只支持两种类型的套接字,SOCK_STREAM指定产生流式套接字,SOCK_DGRAM产生数据报套接字。

protocol参数:与特定的地址家族相关的协议,如果指定为0,那么它就会根据地址格式和套接字类别,自动为你选择一个合适的协议。这是推荐使用的一种选择协议的方法。

3)int bind(SOCKET s, const struct sockaddr FAR *name, int namelen); //将套接字和本地地址联系起来

s参数:指定要绑定的套接字。

name参数:指定了该套接字的本地地址信息。

namelen参数:指定name所指向的sockaddr结构的长度。

四、实例

(1)基于TCP的Socket编程

服务器端,创建一个Win32的控制台应用程序,新建一个cpp文件,取名为Server.cpp,其代码如下:

#pragma comment(lib,"Ws2_32.lib") 

#include <Winsock2.h>
#include <iostream>
using namespace std;
#include <stdio.h>
#include <string.h>

int main()
{
	//********获取应用程序所需的Winsock DLL版本信息
	WORD wVersionRequested;
	wVersionRequested = MAKEWORD(1, 1); //设置高字节为1,低字节为1的WORD类型,表示所需Windows Sockets的版本号为1.1
	WSADATA wsaData; //用来存储获取的Windows Sockets的信息
	int err = WSAStartup(wVersionRequested, &wsaData); //初始化此进程的Winsock DLL的使用
	
	//初始化失败,直接返回
	if (err != 0)
	{
		return 1; 
	}

	//告诉使用者,找不到可用的Winsock DLL
	if (LOBYTE(wsaData.wVersion) != 1 || HIBYTE(wsaData.wVersion) != 1)
	{
		WSACleanup();
		return 1;
	}

	//*********创建套接字
	SOCKET sockServer = socket(AF_INET, SOCK_STREAM, 0);

	//*********将套接字绑定到一个本地地址和端口上
	sockaddr_in addrServer; //存储sock地址信息
	addrServer.sin_addr.S_un.S_addr = htonl(INADDR_ANY); //IP地址为INADDR_ANY,允许套接字向任何分配给本地机器的IP地址发送或接收数据
	addrServer.sin_family = AF_INET; //地址簇
	addrServer.sin_port = htons(6000);

	bind(sockServer, (sockaddr *)&addrServer, sizeof(sockaddr));

	//*********将套接字设为监听模式,准备接收客户请求
	listen(sockServer, 5); //监听的套接字最大数为5

	//*********等待客户请求到来
	sockaddr_in addrClient; //存储sock所连接的客户端的地址信息
	int addrlen = sizeof(sockaddr);

	while (1) 
	{
		//当请求到来后,接受连接请求,返回一个新的对应于此次连接的套接字
		SOCKET sockConnect = accept(sockServer, (sockaddr *)&addrClient, &addrlen); 

		//*********用返回的套接字和客户端进行通信
		char pBuffer[100];
		memset(pBuffer, 0, 100);
		strcat(pBuffer, "Welcome ");
		strcat(pBuffer, inet_ntoa(addrClient.sin_addr));
		strcat(pBuffer, " to http://www.sunxin.org!");
		send(sockConnect, pBuffer, (strlen(pBuffer) + 1) * sizeof(char), 0); //给客户端发送消息

		char recvBuf[100];
		memset(recvBuf, 0, 100);
		recv(sockConnect, recvBuf, 100, 0); //接收客户端发来的消息

		//*********关闭socket连接
		closesocket(sockConnect); 

		cout<<recvBuf<<endl;
	}

	return 0;
}

客户端,创建一个Win32的控制台应用程序,新建一个cpp文件,取名为Client.cpp,其代码如下:

#pragma comment(lib,"Ws2_32.lib") 

#include <Winsock2.h>
#include <iostream>
using namespace std;
#include <stdio.h>
#include <string.h>

int main()
{
	//********获取应用程序所需的Winsock DLL版本信息
	WORD wVersionRequested;
	wVersionRequested = MAKEWORD(1, 1); //设置高字节为1,低字节为1的WORD类型,表示所需Windows Sockets的版本号为1.1
	WSADATA wsaData; //用来存储获取的Windows Sockets的信息
	int err = WSAStartup(wVersionRequested, &wsaData); //初始化此进程的Winsock DLL的使用
	
	//初始化失败,直接返回
	if (err != 0)
	{
		return 1; 
	}

	//告诉使用者,找不到可用的Winsock DLL
	if (LOBYTE(wsaData.wVersion) != 1 || HIBYTE(wsaData.wVersion) != 1)
	{
		WSACleanup();
		return 1;
	}

	//*********创建套接字
	SOCKET sockClient = socket(AF_INET, SOCK_STREAM, 0);

	//*********向服务器发出连接请求
	sockaddr_in addrServer; //存储服务器端的sock地址信息
	addrServer.sin_addr.S_un.S_addr = inet_addr("127.0.0.1"); //服务器IP地址,此处服务器为本机
	addrServer.sin_family = AF_INET; //地址簇
	addrServer.sin_port = htons(6000);

	connect(sockClient, (sockaddr *)&addrServer, sizeof(sockaddr));

	//*********和服务器端进行通信
	char *pBuffer = "This is liuxijiao.";
	send(sockClient, pBuffer, (strlen(pBuffer) + 1) * sizeof(char), 0); //给服务器发送消息

	char recvBuf[100];
	memset(recvBuf, 0, 100);
	recv(sockClient, recvBuf, 100, 0); //接收服务器发来的消息

	//*********关闭socket连接
	closesocket(sockClient); 
	WSACleanup();

	cout<<recvBuf<<endl;
	system("PAUSE");

	return 0;
}

首先运行服务器端的程序,然后再运行客户端的程序。

在服务器端收到客户端发送来的消息:

在客户端收到服务器端发送来的消息:

(2)基于UDP的Socket编程

服务器端,创建一个Win32的控制台应用程序,新建一个cpp文件,取名为Server.cpp,其代码如下:

#pragma comment(lib, "Ws2_32.lib")

#include <Winsock2.h>
#include <iostream>
using namespace std;
#include <stdio.h>
#include <string.h>

int main()
{
	//********获取应用程序所需的Winsock DLL版本信息
	WORD wVersionRequested;
	wVersionRequested = MAKEWORD(1, 1); //设置高字节为1,低字节为1的WORD类型,表示所需Windows Sockets的版本号为1.1
	WSADATA wsaData; //用来存储获取的Windows Sockets的信息
	int err = WSAStartup(wVersionRequested, &wsaData); //初始化此进程的Winsock DLL的使用

	//初始化失败,直接返回
	if (err != 0)
	{
		return 1;
	}

	//告诉使用者,找不到可用的Winsock DLL
	if (LOBYTE(wsaData.wVersion) != 1 || HIBYTE(wsaData.wVersion) != 1)
	{
		WSACleanup();
		return 1;
	}

	//***********创建套接字
	SOCKET sockServer = socket(AF_INET, SOCK_DGRAM, 0);

	//***********将套接字绑定到一个本地地址和端口上
	sockaddr_in addrServer;
	addrServer.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
	addrServer.sin_family = AF_INET;
	addrServer.sin_port = htons(6000);
	bind(sockServer, (sockaddr *)&addrServer, sizeof(sockaddr));

	//***********等待接收数据
	char pBuffer[100];
	memset(pBuffer, 0, 100);
	sockaddr_in addrClient;
	int len = sizeof(sockaddr_in);
	recvfrom(sockServer, pBuffer, 100, 0, (sockaddr *)&addrClient, &len); //接受客户端发来的消息

	//***********关闭套接字
	closesocket(sockServer);

	cout<<pBuffer<<endl;
	system("PAUSE");

	return 0;
}

客户端,创建一个Win32的控制台应用程序,新建一个cpp文件,取名为Client.cpp,其代码如下:

#pragma comment(lib, "Ws2_32.lib")

#include <Winsock2.h>
#include <iostream>
using namespace std;
#include <stdio.h>
#include <string.h>

int main()
{
	//********获取应用程序所需的Winsock DLL版本信息
	WORD wVersionRequested;
	wVersionRequested = MAKEWORD(1, 1); //设置高字节为1,低字节为1的WORD类型,表示所需Windows Sockets的版本号为1.1
	WSADATA wsaData; //用来存储获取的Windows Sockets的信息
	int err = WSAStartup(wVersionRequested, &wsaData); //初始化此进程的Winsock DLL的使用

	//初始化失败,直接返回
	if (err != 0)
	{
		return 1;
	}

	//告诉使用者,找不到可用的Winsock DLL
	if (LOBYTE(wsaData.wVersion) != 1 || HIBYTE(wsaData.wVersion) != 1)
	{
		WSACleanup();
		return 1;
	}

	//***********创建套接字
	SOCKET sockClient = socket(AF_INET, SOCK_DGRAM, 0);

	//***********向服务器发送数据
	char *pBuffer = "Hello, server!";
	sockaddr_in addServer;
	addServer.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
	addServer.sin_family = AF_INET;
	addServer.sin_port = htons(6000);
	sendto(sockClient, pBuffer, (strlen(pBuffer) + 1) * sizeof(char), 0, (sockaddr *)&addServer, sizeof(sockaddr_in));

	//***********关闭套接字
	closesocket(sockClient);

	return 0;
}

首先运行服务器端的程序,然后再运行客户端的程序。可看见在服务器端收到客户端发送来的消息:




 

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值