Winsock编程原理——面向连接
Winsock编程原理——面向连接
Windows Sockets使用套接字进行编程,套接字编程是面向客户端/服务器模型而设计的,因此系统中需要客户端和服务器两个不同类型的进程,根据连接类型的不同,对于面向连接的TCP服务和无连接的UDP服务,服务器分别采取不同的处理操作来对客户提供服务。
面向连接
/*
服务器端代码
*/ #include<Winsock2.h>
#include<stdio.h>
#include<stdlib.h>
#pragma comment(lib,"ws2_32.lib")
#define PORT 5000 void main()
{
int port = PORT; //端口
WSADATA wsaData; //存储系统传回的关于Winsock的资料
SOCKET sListen, sAccept; //套接字
int iLen; //客户地址长度
int iSend; //发送数据长度
char buf[] = "Hello, How are you!"; //需要发送的信息
struct sockaddr_in serv, cliet; //服务器、客户的地址 if (WSAStartup(MAKEWORD(, ), &wsaData) != ) //函数WSAStartup用以打开Winsock
{
printf("Winsock load failed\n");
return;
} sListen = socket(AF_INET, SOCK_STREAM, ); //创建套接字,TCP协议
if (sListen == INVALID_SOCKET) //socket调用成功返回套接字对象,失败返回INVALID_SOCKET
{
printf("socket failed:%d\n", WSAGetLastError());
return;
} serv.sin_family = AF_INET; //网络中标识不同设备使用的地址类型,对于IP地址,类型是AF_INET
serv.sin_port = htons(port); //socket对应的端口号
serv.sin_addr.s_addr = htonl(INADDR_ANY); //封装了IP地址
if (bind(sListen, (LPSOCKADDR)&serv, sizeof(serv)) == SOCKET_ERROR) //绑定套接字
{
printf("bind() failed:%d\n", WSAGetLastError());
return;
} if (listen(sListen, ) == SOCKET_ERROR) //监听
{
printf("listen() failed:%d\n", WSAGetLastError());
return;
} iLen = sizeof(cliet); //初始化客户地址长度 while () //进入循环,等待客户连接请求
{
sAccept = accept(sListen, (struct sockaddr*)&cliet, &iLen); //客户端的套接字
if (sAccept == INVALID_SOCKET) //接受连接请求失败
{
printf("accept() failed:%d\n", WSAGetLastError());
break;
}
//输出客户端IP、端口
printf("accept() client IP:[%s], port:[%d]\n", inet_ntoa(cliet.sin_addr), ntohs(cliet.sin_port)); //给连接的客户发送消息
iSend = send(sAccept, buf, sizeof(buf), );
if (iSend == SOCKET_ERROR)
{
printf("send() failed:%d\n", WSAGetLastError());
break;
}
else if (iSend == )
break;
else
printf("send() byte:%d\n", send); closesocket(sListen); //关闭套接字
closesocket(sAccept); //关闭套接字
WSACleanup(); //关闭Winsock
}
while ();
}
server
/*
客户端程序
*/
#include<WinSock2.h>
#include<stdio.h>
#pragma comment(lib,"ws2_32.lib")
#define PORT 5000
#define BUFFER 1024 void main(int argc,char *argv[])
{
WSADATA wsaData;
SOCKET client;
int port = PORT;
int iLen; //从服务器接收的数据长度
char buf[BUFFER]; //接收数据的缓冲
struct sockaddr_in serv; //服务器端地址
memset(buf, , sizeof(buf)); //接受数据缓冲区初始化 if (WSAStartup(MAKEWORD(, ), &wsaData) != ) //函数WSAStartup用以打开Winsock
{
printf("Winsock load failed\n");
return;
} serv.sin_family = AF_INET; //需要连接服务器地址信息,AF_INET表示IP协议
serv.sin_port = htons(port); //端口
// serv.sin_addr.s_addr = inet_addr(argv[1]); //IP地址,转为二进制表示的字节IP地址,argv表示cmd下输入的参数
serv.sin_addr.s_addr = inet_addr("10.100.211.224");
client = socket(AF_INET, SOCK_STREAM, ); //客户端套接字,流套接字表示使用TCP协议
if (client == INVALID_SOCKET) //创建套接字失败
{
printf("socket() failed:%d\n", WSAGetLastError());
return;
} //连接服务器
if (connect(client, (struct sockaddr*)&serv, sizeof(serv)) == INVALID_SOCKET)
{
printf("connet() failed:%d\n", WSAGetLastError);
return;
}
else
{
iLen = recv(client, buf, sizeof(buf), ); //从服务器接收数据
if (iLen = )
return;
else if (iLen == SOCKET_ERROR)
{
printf("recv() failed:%d\n", WSAGetLastError());
return;
}
printf("recv() data from server:%s\n", buf);
} closesocket(client); //关闭套接字
WSACleanup; //关闭Winsock // system("pause"); //程序暂停
printf("press any key to continue"); //让程序等待
while ();
}
client
加入多线程机制,一个服务器,多个客户端
/*
服务器端代码
*/ #include<Winsock2.h>
#include <windows.h>
#include<stdio.h>
#include<stdlib.h>
#pragma comment(lib,"ws2_32.lib")
#define PORT 5000
class MySocket
{
private:
SOCKET accept;
struct sockaddr_in clientAddr;
public:
MySocket(SOCKET a, struct sockaddr_in c)
{
accept = a;
clientAddr = c;
}
void setAccept(SOCKET a)
{
accept = a;
}
void setClientAddr(struct sockaddr_in c)
{
clientAddr = c;
}
SOCKET getAccept()
{
return accept;
}
struct sockaddr_in getClientAddr()
{
return clientAddr;
}
};
DWORD WINAPI ThreadFuc(LPVOID lparam)
{
MySocket* mSocket = (MySocket*)lparam; //接收主线程传来的参数
char buf[] = "Hello, How are you!"; //需要发送的信息
int iSend = ;
//输出客户端IP、端口
printf("accept() client IP:[%s], port:[%d]\n", inet_ntoa(mSocket->getClientAddr().sin_addr), ntohs(mSocket->getClientAddr().sin_port));
//给连接的客户发送消息
iSend = send(mSocket->getAccept(), buf, sizeof(buf), );
if (iSend == SOCKET_ERROR)
{
printf("send() failed:%d\n", WSAGetLastError());
}
else if (iSend == )
printf("send() failed,no message send successfully\n");
else
printf("send() byte:%d\n", send);
closesocket(mSocket->getAccept()); //关闭套接字
return ;
} void main()
{
int port = PORT; //端口
WSADATA wsaData; //存储系统传回的关于Winsock的资料
SOCKET sListen, sAccept; //套接字
int iLen; //客户地址长度
struct sockaddr_in serv, cliet; //服务器、客户的地址 if (WSAStartup(MAKEWORD(, ), &wsaData) != ) //函数WSAStartup用以打开Winsock
{
printf("Winsock load failed\n");
return;
} sListen = socket(AF_INET, SOCK_STREAM, ); //创建套接字,TCP协议
if (sListen == INVALID_SOCKET) //socket调用成功返回套接字对象,失败返回INVALID_SOCKET
{
printf("socket failed:%d\n", WSAGetLastError());
return;
} serv.sin_family = AF_INET; //网络中标识不同设备使用的地址类型,对于IP地址,类型是AF_INET
serv.sin_port = htons(port); //socket对应的端口号
serv.sin_addr.s_addr = htonl(INADDR_ANY); //封装了IP地址
if (bind(sListen, (LPSOCKADDR)&serv, sizeof(serv)) == SOCKET_ERROR) //绑定套接字
{
printf("bind() failed:%d\n", WSAGetLastError());
return;
} if (listen(sListen, ) == SOCKET_ERROR) //监听
{
printf("listen() failed:%d\n", WSAGetLastError());
return;
} iLen = sizeof(cliet); //初始化客户地址长度 while () //进入循环,等待客户连接请求
{
sAccept = accept(sListen, (struct sockaddr*)&cliet, &iLen); //客户端的套接字
if (sAccept == INVALID_SOCKET) //接受连接请求失败
{
printf("accept() failed:%d\n", WSAGetLastError());
break;
}
else
{
MySocket* mSocket = new MySocket(sAccept, cliet);
HANDLE thread = CreateThread(NULL, NULL, ThreadFuc, mSocket, NULL, NULL);
// closesocket(sAccept);不能关闭,关闭则不行。
}
}
closesocket(sListen); //关闭套接字
WSACleanup(); //关闭Winsock
while ();
}
server
/*
客户端程序
*/
#include<WinSock2.h>
#include<stdio.h>
#pragma comment(lib,"ws2_32.lib")
#define PORT 5000
#define BUFFER 1024 void main(int argc, char *argv[])
{
WSADATA wsaData;
SOCKET client;
int port = PORT;
int iLen; //从服务器接收的数据长度
char buf[BUFFER]; //接收数据的缓冲
struct sockaddr_in serv; //服务器端地址
memset(buf, , sizeof(buf)); //接受数据缓冲区初始化 if (WSAStartup(MAKEWORD(, ), &wsaData) != ) //函数WSAStartup用以打开Winsock
{
printf("Winsock load failed\n");
return;
} serv.sin_family = AF_INET; //需要连接服务器地址信息,AF_INET表示IP协议
serv.sin_port = htons(port); //端口
// serv.sin_addr.s_addr = inet_addr(argv[1]); //IP地址,转为二进制表示的字节IP地址,argv表示cmd下输入的参数
serv.sin_addr.s_addr = inet_addr("192.168.0.21");
client = socket(AF_INET, SOCK_STREAM, ); //客户端套接字,流套接字表示使用TCP协议
if (client == INVALID_SOCKET) //创建套接字失败
{
printf("socket() failed:%d\n", WSAGetLastError());
return;
} //连接服务器
if (connect(client, (struct sockaddr*)&serv, sizeof(serv)) == INVALID_SOCKET)
{
printf("connet() failed:%d\n", WSAGetLastError);
return;
}
else
{
iLen = recv(client, buf, sizeof(buf), ); //从服务器接收数据
if (iLen = )
return;
else if (iLen == SOCKET_ERROR)
{
printf("recv() failed:%d\n", WSAGetLastError());
return;
}
printf("recv() data from server:%s\n", buf);
} closesocket(client); //关闭套接字
WSACleanup; //关闭Winsock // system("pause"); //程序暂停
printf("press any key to continue"); //让程序等待
while ();
}
client
Winsock编程原理——面向连接的更多相关文章
- socket编程原理
socket编程原理 1.问题的引入 1) 普通的I/O操作过程: UNIX系统的I/O命令集,是从Maltics和早期系统中的命令演变出来的,其模式为打开一读/写一关闭(open-write-rea ...
- 第1章 网络编程基础(2)——Socket编程原理
Socket编程原理 Socket是网络通信端点的一种抽象,它提供了一种发送和接收数据的机制. 流socket(SOCK_STREAM):双向.有序.无重复.并且无记录边界 数据报Socket(SOC ...
- Winsock编程基础介绍 .
相信很多人都对网络编程感兴趣,下面我们就来介绍,在网络编程中应用最广泛的编程接口Winsock API. 使用Winsock API的编程,应该了解一些TCP/IP的基础知识.虽然你可以直接使用Win ...
- 【VS开发】socket编程原理
socket编程原理 1.问题的引入 1) 普通的I/O操作过程: UNIX系统的I/O命令集,是从Maltics和早期系统中的命令演变出来的,其模式为打开一读/写一关闭(open-write-rea ...
- NetBIOS与Winsock编程接口
最近在看网络编程方面的书,由于不是通信专业出身的,以前理解的网络体系感觉就是tcp/ip,最近工作上接触到了一些光环网等乱七八糟的东西,有些基本的LC.SC连接器都不认识.花时间看了下计算机网络体系结 ...
- Winsock 编程流程
近期看了<Window程序设计>感觉在网络方面讲的不错,讲的非常通俗易懂.与大家一同交流 转载请注明出处:http://blog.csdn.net/u010484477谢谢^_^ 使用 W ...
- Delphi下的WinSock编程
一.定址 要通过Winsock建立通信,必须了解如何利用指定的协议为工作站定址.Winsock 2引入了几个新的.与协议无关的函数,它们可和任何一个地址家族一起使用:但是大多数情况下,各 ...
- Winsock 编程详解
转载请注明出处!本文地址:https://www.cnblogs.com/teternity/p/WinSock.html Winsock 编程 目录 通用函数讲解 WSAStartup WSACle ...
- JavaScript异步编程原理
众所周知,JavaScript 的执行环境是单线程的,所谓的单线程就是一次只能完成一个任务,其任务的调度方式就是排队,这就和火车站洗手间门口的等待一样,前面的那个人没有搞定,你就只能站在后面排队等着. ...
随机推荐
- Sass函数-join()函数
join() 函数是将两个列表连接合并成一个列表. >> join(10px 20px, 30px 40px) (10px 20px 30px 40px) >> join((b ...
- postcss-px-to-viewport 的 exclude 配置无效
原来是由于版本太低的缘故: postcss-px-to-viewport 0.0.3版本不支持 exclude属性. 更新到 1.1.0 配置: // 路径中包含 PC ,则忽略 px转换为vw,vh ...
- Codeforces Global Round 1 (CF1110) (未完结,只有 A-F)
Codeforces Global Round 1 (CF1110) 继续补题.因为看见同学打了这场,而且涨分还不错,所以觉得这套题目可能会比较有意思. 因为下午要开学了,所以恐怕暂时不能把这套题目补 ...
- 唐太宗灵州勒石 TANGTAIZONGLINZHOULESHI
唐太宗灵州勒石 唐贞观二十年(646年),在唐军和回纥部落联合打败突厥薛延陀部后,原归附薛延陀部的回纥.拔野古.斛薛等部族,越过贺兰山,进入了今宁夏的银川.吴忠一带地区.这些总族向唐朝提出,愿意臣服唐 ...
- mysql中的key primary key 和unique key
mysql 中key就等同于index 所以 key:普通索引 unique key:唯一索引,就是这一列不能重复 primary key:主键索引,就是不能为空,且主键索引不是完全相同时,插入新数据 ...
- Vue通信的10种方式
1.10种通信方式 10种:https://juejin.im/post/5bd18c72e51d455e3f6e4334 2.除此之外,还有children和ref. 需要注意 $children ...
- Dataphin的代码自动化能力如何助力商业决策
前言 随着大数据趋势的迅速增长,数据的重要性与日俱增,企业内看数据.用数据的诉求越来越强烈,其中最常见的就是各种经营报表数据:老板每日早晨9点准时需要看到企业核心的经营数据,以便进行企业战略及方向决策 ...
- 组合的输出(回溯、dfs)
问题 O: [回溯法]组合的输出 题目描述 排列与组合是常用的数学方法,其中组合就是从n个元素中抽出r个元素(不分顺序且r<=n),我们可以简单地将n个元素理解为自然数1,2,…,n,从中任取r ...
- NOIp 图论算法专题总结 (3):网络流 & 二分图 简明讲义
系列索引: NOIp 图论算法专题总结 (1) NOIp 图论算法专题总结 (2) NOIp 图论算法专题总结 (3) 网络流 概念 1 容量网络(capacity network)是一个有向图,图的 ...
- QString的arg方法
第一个参数是要填充的数字,第二个参数为最小宽度,第三个参数为进制,第四个参数为当原始数字长度不足最小宽度时用于填充的字符,如 QString name=QString("R%1C%2&quo ...