您的位置:首页 > 编程语言

windows Socket编程

2016-04-08 22:10 218 查看
windows下socket编程有两种方式,tcp和udp

通常我们在说到网络编程时默认是指TCP编程,即用前面提到的socket函数创建一个socket用于TCP通讯,函数参数我们通常填为SOCK_STREAM。即socket(PF_INET, SOCK_STREAM, 0),这表示建立一个socket用于流式网络通讯。

SOCK_STREAM这种的特点是面向连接的,即每次收发数据之前必须通过connect建立连接,也是双向的,即任何一方都可以收发数据,协议本身提供了一些保障机制保证它是可靠的、有序的,即每个包按照发送的顺序到达接收方。

而SOCK_DGRAM这种是User Datagram Protocol协议的网络通讯,它是无连接的,不可靠的,因为通讯双方发送数据后不知道对方是否已经收到数据,是否正常收到数据。任何一方建立一个socket以后就可以用sendto发送数据,也可以用recvfrom接收数据。根本不关心对方是否存在,是否发送了数据。它的特点是通讯速度比较快。大家都知道TCP是要经过三次握手的,而UDP没有。

基于上述不同,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、关闭网络连接;

Tcp服务器

#pragma comment(lib, "ws2_32.lib")
#include <winsock2.h>
#include <stdio.h>
int main()
{
SOCKET mysock,tsock;              // 定义套接字
struct sockaddr_in my_addr;       // 本地地址信息
struct sockaddr_in their_addr;     // 连接者地址信息
int sin_size;
WSADATA wsa;
WSAStartup(MAKEWORD(2,2),&wsa);       //初始化Windows Socket
//建立socket
mysock = socket(AF_INET, SOCK_STREAM, 0);
//bind本机的端口
my_addr.sin_family = AF_INET;               // 协议类型是INET
my_addr.sin_port = htons(1234);           // 绑定端口1234
my_addr.sin_addr.s_addr = INADDR_ANY;   // 本机IP
bind(mysock, (struct sockaddr *)&my_addr, sizeof(struct sockaddr));
//listen,监听端口
listen(mysock, 10); // 等待连接数目
printf("listen......");
//等待客户端连接
sin_size = sizeof(struct sockaddr_in);
tsock = accept(mysock, (struct sockaddr *)&their_addr, &sin_size);
//有连接就发送Hello!字符串过去
send(tsock, "Hello!\n", sizeof("Hello!\n"), 0);
printf("send ok!\n");
//成功,关闭套接字
closesocket(mysock);
closesocket(tsock);
return 0;
}


程序运行后,服务器端显示listen,通过telnet目标主机ip:端口号,连接后显示“hello”

Udp socket服务器

#include <winsock2.h>
#include <stdio.h>
BOOL InitWinsock();
void main()
{
SOCKET socket1;

InitWinsock();
struct sockaddr_in server;
int len =sizeof(server);
server.sin_family=AF_INET;
server.sin_port=htons(1000);                      ///server的监听端口
server.sin_addr.s_addr=inet_addr("12.1.34.217"); ///server的地址

socket1=socket(AF_INET,SOCK_DGRAM,0);
while (1)
{

char buffer[1024]="\0";
printf("input message\n");
scanf("%s",buffer);
if (strcmp(buffer,"bye")==0)
break;
if (sendto(socket1,buffer,sizeof buffer,0,(struct sockaddr*)&server,len)!=SOCKET_ERROR)
{
if (recvfrom(socket1,buffer,sizeof buffer,0,(struct sockaddr*)&server,&len)!=SOCKET_ERROR)
printf("rece from server:%s\n",buffer);
}
}
closesocket(socket1);
}

BOOL InitWinsock()
{
int Error;
WORD VersionRequested;
WSADATA WsaData;
VersionRequested=MAKEWORD(2,2);
Error=WSAStartup(VersionRequested,&WsaData); //启动WinSock2
if(Error!=0)
{
return FALSE;
}
else
{
if(LOBYTE(WsaData.wVersion)!=2||HIBYTE(WsaData.wHighVersion)!=2)
{
WSACleanup();
return FALSE;
}

}
return TRUE;
}


udp socket 客户端

#include <winsock2.h>
#include <stdio.h>
BOOL InitWinsock();
void main()
{
SOCKET socket1;

InitWinsock();
struct sockaddr_in local;
struct sockaddr_in from;
int fromlen =sizeof(from);
local.sin_family=AF_INET;
local.sin_port=htons(1000);             ///监听端口
local.sin_addr.s_addr=INADDR_ANY;       ///本机

socket1=socket(AF_INET,SOCK_DGRAM,0);

bind(socket1,(struct sockaddr*)&local,sizeof local);

while (1)
{
char buffer[1024]="\0";
printf("waiting for message from others-------------\n");
if (recvfrom(socket1,buffer,sizeof buffer,0,(struct sockaddr*)&from,&fromlen)!=SOCKET_ERROR)
{
printf("Received datagram from %s--%s\n",inet_ntoa(from.sin_addr),buffer);
////给cilent发信息
sendto(socket1,buffer,sizeof buffer,0,(struct sockaddr*)&from,fromlen);

}
Sleep(500);
}

closesocket(socket1);

}

BOOL InitWinsock()
{
int Error;
WORD VersionRequested;
WSADATA WsaData;
VersionRequested=MAKEWORD(2,2);
Error=WSAStartup(VersionRequested,&WsaData); //启动WinSock2
if(Error!=0)
{
return FALSE;
}
else
{
if(LOBYTE(WsaData.wVersion)!=2||HIBYTE(WsaData.wHighVersion)!=2)
{
WSACleanup();
return FALSE;
}

}
return TRUE;
}


wsasocket

socket()创建一个通讯端点并返回一个套接口。但是在socket库中例程在应用于阻塞套接口时会阻塞。

WSASocket()的发送操作和接收操作都可以被重叠使用。接收函数可以被多次调用,发出接收缓冲区,准备接收到来的数据。发送函数也可以被多次调用,组成一个发送缓冲区队列。 可是socket()却只能发过之后等待回消息才可做下一步操作!

Header: Declared in Winsock2.h.
Library: Use Ws2_32.lib.

SOCKET WSASocket(
int af,
int type,
int protocol,
LPWSAPROTOCOL_INFO lpProtocolInfo,
GROUP g,
DWORD dwFlags
);
af:地址族描述。目前仅支持PF_INET格式,亦即ARPA Internet地址格式。
type:新套接口的类型描述。
protocol:套接口使用的特定协议,如果调用者不愿指定协议则定为0。
lpProtocolInfo:一个指向PROTOCOL_INFO结构的指针,该结构定义所创建套接口的特性。如果本参数非零,则前三个参数(af, type, protocol)被忽略。
g:套接口组的描述字。
iFlags:套接口属性描述。
返回值:
若无错误发生,WSASocket()返回新套接口的描述字。否则的话,返回 INVALID_SOCKET,应用程序可以调用WSAGetLastError()来获取相应的错误代码。
错误代码:
WSANOTINITIALISED            在调用本API之前应成功调用WSAStartup()。
WSAENETDOWN                  网络子系统失效。
WSAEAFNOSUPPORT              不支持指定的地址族。
WSAEINPROGRESS               一个阻塞的WinSock调用正在进行中,或者服务提供者仍在处理一个回调函数WSAEMFILE                    无可用的套接口描述字。
WSAENOBUFS                   无可用的缓冲区空间。套接口无法创建。
WSAEPROTONOSUPPORT           不支持指定的协议。
WSAEPROTOTYPE                指定的协议对于本套接口类型错误。
WSAESOCKTNOSUPPORT           本地址族不支持指定的套接口类型。
WSAEINVAL                    g参数非法。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: