Winsock编程原理

面向连接的系统调用

面向无连接的系统调用

 

1.Winsock的打开
int WSAStartup(WORD wVersionRequested, LPWSADATA lpWSAData);
成功返回0,失败返回不同的错误信息。

2.服务器建立套接字
SOCKET socket(int af, int type, int protocol);
成功返回套接字对象,失败返回INVALID_SOCKET
af:说明套接口要使用的协议地址族,目前只提供AF_INET表示互联网(IP)协议。
type:描述套接字的类型,只能是SOCK_STREAM,SOCK_DGRAM,SOCK_RAW 3个协议中的一个,分别表示流套接字,数据报套接字和原始套接字
protocol:该套接字使用的特定通信协定(如果使用者不指定则为0)

3.服务器绑定端口
int bind(SOCKET s, const sockaddr FAR* name, int namelen);
成功返回0,失败返回SOCKET_ERROR
s:表示未绑定的套接字的对象名,他是socket()函数调用成功时返回的值。
name:套接字的地址值,是一个与指定协议有关的地址结构指针,这个地址必须是执行这个程式所在的机器的IP地址,
在winsock中使用sockaddr_in结构指定IP地址和端口信息,定义如下:
struct sockaddr_in
{
 short sin_family;
 u_short sin_port;
 struct in_addr sin_addr;
 char sin_zero[8];
};
其中sin_family必须为AF_INET,指明使用的是IP地址族;sin_port和sin_addr分别是以网络字节顺序表示的16位端口号和32位IP地址,
sin_zero字段一般为0;
namelen:地址参数name的长度。

4.客户端提出连接申请
int PASCAL FAR connection(SOCKET s, const struct sockaddr FAR* name, int namelen);
s:socket的识别码
name:socket想要连接的对方地址
namelen:name的长度监听
当服务端的套接字对象绑定完成之后,服务器端需要一个监听的队列来接收客户端的连接请求.listen()函数是服务器端的套接字进入监听状态。
int listen(SOCKET s, int backlog);
成功返回0,失败返回SOCKET_ERROR
s:表明一个已经绑定了的地址,需要建立监听的套接字
backlog:指定正在等待连接的最大连接个数。
服务器端调用accept()函数完成建立连接,为了知道什么时候客户端提出连接要求,从而服务器端的套接口在恰当的时候调用accept()函数完成连接的建立,需要使用
WSAAsyncSelect()函数,让系统主动通知有客户端提出连接请求了。
int  WSAAsyncSelect(SOCKET s, HWND hWnd, unsigned int wMsg, long lEvent);
s:套接字对象
hWnd:接收消息的窗口句柄
wMsg:传给窗口的消息
IEvent:被注册的网络时间,也即是应用程序向窗口发送消息的网路事件。该值为下列值FD_READ,FD_WRITE,FD_OOB,FD_CONNECT,FD_CLOSE的组合
可以再窗口处理自定义消息函数中使用以下结构来响应Socket的不同事件:
switch(lParam)
{
 case FD_READ:
  ...
  bread;
 case FD_WRITE:
  ...
  break;
 ...
}

5.服务器端接受客户端的连接请求
SOCKET accept(SCOKET s, struct sockaddr FAR* addr, int FAR* addrlen);
调用成功,返回一个新的套接字对象与客户端的套接字相通。失败返回INVALID_SOCKET.
s:Socket的识别码
addr:存放来连接的客户端的地址
addrlen:addr的长度

6.数据的传送
int send(SOCKET s, const char FAR* buf, int len, int flags);
成功返回发送资料的长度,失败返回SOCKET_ERROR
s:socket的识别码
buf:存放要传送的资料的暂存区
len:buf的长度
flags:此函数被调用的方式
int recv(SOCKET s, char FAR* buf, int len, int flags);
成功返回接收资料的长度,失败返回SOCKET_ERROR
s:socket的识别码
buf:存放要接收的资料的暂存区
len:buf的长度
flags:此函数被调用的方式输入缓存内有效的资料,但其数量不超过len的大小

7.关闭套接字
int closesocket(SOCKET s);

8.关闭Winsock
int WSACleanup(void); //对应每个WSAStartup()函数,必须有一个WSACleanup()函数的调用

实例代码:

1)服务器端代码

View Code
 1 #include <WinSock2.h>
 2 #include <iostream>
 3 #include <cstdlib>
 4 #pragma comment(lib,"ws2_32.lib")
 5 using namespace std;
 6 
 7 #define PORT 5000
 8 int main()
 9 {
10     int port = PORT;
11     WSADATA wsaData;
12     if (WSAStartup(MAKEWORD(2,2),&wsaData) != 0)
13     {
14         perror("winsock load failed!\n");
15         return 1;
16     }
17     //创建套接字
18     SOCKET sListen = socket(AF_INET, SOCK_STREAM, 0);
19     if (sListen == INVALID_SOCKET)
20     {
21         perror("create socket faild! \n");
22         return 1;
23     }
24     //建立服务器地址
25     struct sockaddr_in serv;
26     struct sockaddr_in client;
27     serv.sin_family = AF_INET;    
28     //把一个双字节主机字节顺序的数据转换为网络字节顺序
29     serv.sin_port = htons(port);
30     //把四字节主机字节顺序转换为网络字节顺序,INADDR_ANY为系统指定的IP地址
31     serv.sin_addr.s_addr = htonl(INADDR_ANY);
32     if (bind(sListen, (LPSOCKADDR)&serv, sizeof(serv)) == SOCKET_ERROR)
33     {
34         perror("bind socket failed ! \n");
35         return 1;
36     }
37     //进入监听状态
38     if (listen(sListen,5) == SOCKET_ERROR)
39     {
40         perror("listen socket failed! \n");
41         return 1;
42     }
43     //进入循环等待客户端连接
44     int iLen = sizeof(client);
45     while(1)
46     {
47         SOCKET sAccept = accept(sListen, (LPSOCKADDR)&client, &iLen);
48         if (sAccept == INVALID_SOCKET)
49         {
50             perror("accept socket failed! /n");
51             break;
52         }
53         printf("accepted client IP:[%s],port:[%d]\n", inet_ntoa(client.sin_addr),ntohs(client.sin_port));
54 
55         //给连接的客户发消息
56         char buf[] = "hello client,i am server!";
57         int iSend = send(sAccept,buf,sizeof(buf),0);
58         if (iSend == SOCKET_ERROR)
59         {
60             perror("send buf failed \n");
61             break;
62         }
63         else if (iSend == 0)
64         {
65             break;
66         }
67         else
68             printf("send()byte:%d \n",iSend);
69         printf("********************\n");
70         char recv_buf[1024] = {0};
71         int recv_len = recv(sAccept,recv_buf,sizeof(recv_buf),0);
72         if (recv_len == SOCKET_ERROR)
73         {
74             perror("server recv failed \n");
75             return 1;
76         }
77         else{
78             printf("recv from client:%s \n",recv_buf);
79         }
80     }
81 
82 
83     closesocket(sListen);
84     WSACleanup();
85     //return 0;
86 }

2)客户端代码

View Code
 1 #include <WinSock2.h>
 2 #include <iostream>
 3 #include <cstdlib>
 4 #pragma comment (lib,"ws2_32.lib")
 5 using namespace std;
 6 
 7 #define PORT 5000
 8 #define BUFFER 1024
 9 int main(int argc,  char* argv[])
10 {
11     //初始化socket
12     WSADATA wsaData;
13     if(0 != WSAStartup(MAKEWORD(2,2),&wsaData))
14     {
15         perror("winsock load failed \n");
16         return 1;
17     }
18     //建立客户端流套接字
19     SOCKET client = socket(AF_INET,SOCK_STREAM,0);
20     if (client == INVALID_SOCKET)
21     {
22         perror("create socket failed\n");
23         return 1;
24     }
25     //连接服务端
26     struct sockaddr_in serv;
27     serv.sin_family = AF_INET;    //需要连接的服务器地址信息
28     int port = PORT;
29     serv.sin_port = htons(port);
30     serv.sin_addr.s_addr = inet_addr(argv[1]);    //将命令行的IP地址转化为二进制表示的网络字节书序IP地址
31     if (connect(client,(const struct sockaddr*)&serv,sizeof(serv)) == INVALID_SOCKET)
32     {
33         perror("connect faild\n");
34         return 1;
35     }
36     else
37     {
38         char buf[BUFFER] = {0};
39         int iLen = recv(client,buf,sizeof(buf),0);
40         if (iLen == SOCKET_ERROR)
41         {
42             perror("recv data failed \n");
43             return 1;
44         }
45         printf("recv() data from server:%s\n",buf);
46         char send_buf[] = "hello server, i am client.";
47         int send_len = send(client,send_buf,sizeof(send_buf),0);
48         if (send_len == SOCKET_ERROR)
49         {
50             perror("client send failed \n");
51             return 1;
52         }
53         else
54             printf("send()bytes: %d\n",send_len);
55     }
56     closesocket(client);
57     WSACleanup();
58     printf("please wait..........");
59     while(1);
60 
61 }

 

转载于:https://www.cnblogs.com/kkkwar/archive/2012/05/02/2479401.html

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值