winsocket入门学习
参考资料:http://c.biancheng.net/cpp/socket/
http://www.winsocketdotnetworkprogramming.com/
socket 是“套接字”意思,是计算机之间进行通信的一种约定。
通过 socket 这种约定,一台计算机可以接收其他计算机的数据,也可以向其他计算机发送数据。
学习 socket,也就是学习计算机之间如何通信,并编写出实用的程序。
WD--返回WinSock的实现信息。
WD是一个WSAData结构:
typedef struct WSAData {
WORD wVersion;
WORD wHighVersion;
#ifdef _WIN64
unsigned short iMaxSockets;
unsigned short iMaxUdpDg;
char FAR * lpVendorInfo;
char szDescription[WSADESCRIPTION_LEN+1];
char szSystemStatus[WSASYS_STATUS_LEN+1];
#else
char szDescription[WSADESCRIPTION_LEN+1];
char szSystemStatus[WSASYS_STATUS_LEN+1];
unsigned short iMaxSockets;
unsigned short iMaxUdpDg;
char FAR * lpVendorInfo;
#endif
} WSADATA, FAR * LPWSADATA;
最简单的WinSocket程序
server.c
#define _WINSOCK_DEPRECATED_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <winsock2.h>
#pragma comment(lib, "ws2_32.lib")
#define BUFFER_SIZE 1024 int main()
{
WSADATA wsaData; //包含系统所支持的WinSocket版本信息
SOCKET sServer; //服务器Socket,用于监听客户端请求
SOCKET sClient; //客户端Socket,用于实现与客户端的通信
int retVal; //调用各种Socket函数的返回值
char buf[BUFFER_SIZE]; //用于接受客户端数据的缓冲区 //初始化WinSocket 2.2
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
{
printf("WSAStartup failed!\n");
return -1;
} /**
* 打印socket信息
* 低位字节存储主版本号,高位字节存储副版本号
*/
printf("[wVersion] = %d.%d\n", LOBYTE(wsaData.wVersion), HIBYTE(wsaData.wVersion));
printf("[wHighVersion] = %d.%d\n", LOBYTE(wsaData.wHighVersion), HIBYTE(wsaData.wHighVersion));
printf("[szDescription] = %s\n", wsaData.szDescription);
printf("[szSystemStatus] = %s\n", wsaData.szSystemStatus);
printf("[iMaxSockets] = %d\n", wsaData.iMaxSockets);
printf("[iMaxUdpDg] = %d\n", wsaData.iMaxUdpDg); //创建用于监听的socket
sServer = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (sServer == INVALID_SOCKET)
{
printf("socket failed!\n");
WSACleanup();
return -1;
} /**
* 设置服务器socket地址
* 服务器监听地址为INADDR_ANY-->在任意本地地址(0.0.0.0)监听
* 监听端口号为9999
*/
SOCKADDR_IN addrServ;
addrServ.sin_family = AF_INET;
addrServ.sin_port = htons(9999);
addrServ.sin_addr.S_un.S_addr = htonl(INADDR_ANY); //绑定Sockets Server到本地地址
retVal = bind(sServer, (const struct sockaddr*)&addrServ, sizeof(SOCKADDR_IN));
if (retVal == SOCKET_ERROR)
{
printf("bind failed!\n");
closesocket(sServer);
WSACleanup();
return -1;
} //在Sockets Server上进行监听
retVal = listen(sServer, 1);
if (retVal == SOCKET_ERROR)
{
printf("listen failed!\n");
closesocket(sServer);
WSACleanup();
return -1;
} //接受来自客户端的请求
printf("TCP Server start...\n");
struct sockaddr_in addrClient;
int addrClientlen = sizeof(addrClient);
sClient = accept(sServer, (struct sockaddr FAR *)&addrClient, &addrClientlen);
if (sClient == INVALID_SOCKET)
{
printf("accept failed!\n");
closesocket(sServer);
WSACleanup();
return -1;
} //printf("%s\n", inet_ntoa(addrClient.sin_addr)); while (1)
{
//清空接收数据的缓冲区
memset(buf, 0, sizeof(buf));
retVal = recv(sClient, buf, BUFFER_SIZE, 0);
if (retVal == SOCKET_ERROR)
{
printf("recv failed\n");
closesocket(sServer);
closesocket(sClient);
WSACleanup();
return -1;
}
SYSTEMTIME st;
GetLocalTime(&st);
char szDateTime[50];
sprintf(szDateTime, "%4d-%02d-%02d %02d:%02d:%02d", st.wYear, st.wMonth, st.wDay,
st.wHour, st.wMinute, st.wSecond); //打印输出信息
printf("%s, Recv From Client [%s:%d] :%s\n", szDateTime, inet_ntoa(addrClient.sin_addr), addrClient.sin_port, buf); if (strcmp(buf, "quit") == 0)
{
send(sClient, "quit", strlen("quit"), 0);
break;
}
else
{
char msg[BUFFER_SIZE];
sprintf(msg, "Message received - %s", buf);
retVal = send(sClient, msg, strlen(msg), 0);
if (retVal == SOCKET_ERROR)
{
printf("send failed\n");
closesocket(sServer);
closesocket(sClient);
WSACleanup();
return -1;
}
}
} //清除工作
closesocket(sServer);
closesocket(sClient);
WSACleanup(); return 0;
}
client.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <winsock2.h>
#pragma comment(lib, "ws2_32.lib")
#define BUFFER_SIZE 1024 int main()
{
WSADATA wsaData;
SOCKET sHost;
int retVal;
char buf[BUFFER_SIZE]; if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
{
printf("WSAStartup failed!\n");
return -1;
} sHost = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (sHost == INVALID_SOCKET)
{
printf("socket failed!\n");
WSACleanup();
return -1;
} SOCKADDR_IN addrServ;
addrServ.sin_family = AF_INET;
addrServ.sin_port = htons(9999);
addrServ.sin_addr.S_un.S_addr = inet_addr("127.0.0.1"); retVal = connect(sHost, (LPSOCKADDR)&addrServ, sizeof(SOCKADDR_IN));
if (retVal == SOCKET_ERROR)
{
printf("connect failed!\n");
closesocket(sHost);
WSACleanup();
return -1;
} while (1)
{
printf("Please input a string:");
gets(buf);
retVal = send(sHost, buf, strlen(buf), 0);
if (retVal == SOCKET_ERROR)
{
printf("send failed!\n");
closesocket(sHost);
WSACleanup();
return -1;
}
memset(buf, 0, sizeof(buf));
retVal = recv(sHost, buf, sizeof(buf), 0);
if (retVal == SOCKET_ERROR)
{
printf("recv failed!\n");
closesocket(sHost);
WSACleanup();
return -1;
}
printf("Recv From Server: %s\n", buf);
if(strcmp(buf, "quit") == 0)
{
break;
}
} //วๅณนคื๗
closesocket(sHost);
WSACleanup(); return 0;
}
对于完成的client/server程序可以使用NC来测试
| 1)连接到 remote 主机,例子: 格式:nc -nvv 192.168.x.x 80 讲解:连到192.168.x.x的TCP80端口 2)监听 local 主机,例子: 格式:nc -l -p 80 讲解:监听本机的TCP80端口 |
winsocket入门学习的更多相关文章
- vue入门学习(基础篇)
vue入门学习总结: vue的一个组件包括三部分:template.style.script. vue的数据在data中定义使用. 数据渲染指令:v-text.v-html.{{}}. 隐藏未编译的标 ...
- Hadoop入门学习笔记---part4
紧接着<Hadoop入门学习笔记---part3>中的继续了解如何用java在程序中操作HDFS. 众所周知,对文件的操作无非是创建,查看,下载,删除.下面我们就开始应用java程序进行操 ...
- Hadoop入门学习笔记---part3
2015年元旦,好好学习,天天向上.良好的开端是成功的一半,任何学习都不能中断,只有坚持才会出结果.继续学习Hadoop.冰冻三尺,非一日之寒! 经过Hadoop的伪分布集群环境的搭建,基本对Hado ...
- PyQt4入门学习笔记(三)
# PyQt4入门学习笔记(三) PyQt4内的布局 布局方式是我们控制我们的GUI页面内各个控件的排放位置的.我们可以通过两种基本方式来控制: 1.绝对位置 2.layout类 绝对位置 这种方式要 ...
- PyQt4入门学习笔记(一)
PyQt4入门学习笔记(一) 一直没有找到什么好的pyqt4的教程,偶然在google上搜到一篇不错的入门文档,翻译过来,留以后再复习. 原始链接如下: http://zetcode.com/gui/ ...
- Hadoop入门学习笔记---part2
在<Hadoop入门学习笔记---part1>中感觉自己虽然总结的比较详细,但是始终感觉有点凌乱.不够系统化,不够简洁.经过自己的推敲和总结,现在在此处概括性的总结一下,认为在准备搭建ha ...
- Retrofit 入门学习
Retrofit 入门学习官方RetrofitAPI 官方的一个例子 public interface GitHubService { @GET("users/{user}/repos&qu ...
- MyBatis入门学习教程-使用MyBatis对表执行CRUD操作
上一篇MyBatis学习总结(一)--MyBatis快速入门中我们讲了如何使用Mybatis查询users表中的数据,算是对MyBatis有一个初步的入门了,今天讲解一下如何使用MyBatis对use ...
- opengl入门学习
OpenGL入门学习 说起编程作图,大概还有很多人想起TC的#include <graphics.h>吧? 但是各位是否想过,那些画面绚丽的PC游戏是如何编写出来的?就靠TC那可怜的640 ...
随机推荐
- $Luogu2512/CH122/AcWing122$糖果传递 模拟
$Luogu$ $AcWing$ $Description$ 有$n$个小朋友坐成一圈,每人有$a_i$个糖果. 每人只能给左右两人传递糖果. 每人每次传递一个糖果代价为$1$. 求使所有人获得均等 ...
- 「2018-11-05模拟赛」T5 传送机 解题报告
5.传送机(sent.*) 问题描述: 黄黄同学要到清华大学上学去了.黄黄同学很喜欢清华大学的校园,每次去上课时总喜欢把校园里面的每条路都走一遍,当然,黄黄同学想每条路也只走一遍. 我们一般人很可能对 ...
- 「洛谷P1402」酒店之王 解题报告
P1402 酒店之王 题目描述 XX酒店的老板想成为酒店之王,本着这种希望,第一步要将酒店变得人性化.由于很多来住店的旅客有自己喜好的房间色调.阳光等,也有自己所爱的菜,但是该酒店只有p间房间,一天只 ...
- 一次 kafka 消息堆积问题排查
收到某业务组的小伙伴发来的反馈,具体问题如下: 项目中某 kafka 消息组消费特别慢,有时候在 kafka-manager 控制台看到有些消费者已被踢出消费组. 从服务端日志看到如下信息: 该消费组 ...
- 细说javascript typeof操作符
细说javascript typeof操作符 typeof定义 typeof是一元运算符,用来返回操作数类型的字符串.下面是ECAMScript5.1关于typeof的标准定义: NOTE:上面表格标 ...
- C#支付宝支付接口H5版(手机网页支付)
接口官方文档 https://docs.open.alipay.com/203/107090/ 首先在Nuget 安装 Alipay /// <summary> /// 支 ...
- MySQL快速回顾:高级查询操作
8.1 排序数据 检索出的数据并不是以纯粹的随机顺序显示的.如果不排序,数据一般将以它在底层表中出现的顺序显示.这可以是数据最初添加到表中的顺序.但是,如果数据后来进行过更新或删除,则此顺序将会受到M ...
- Spring Boot2 系列教程 (十三) | 整合 MyBatis (XML 版)
前言 如题,今天介绍 SpringBoot 与 Mybatis 的整合以及 Mybatis 的使用,之前介绍过了 SpringBoot 整合MyBatis 注解版的使用,上一篇介绍过 MyBatis ...
- Java 使用Scanner时的NoSuchElementException异常
做实验时设计了一个类,在类中的两个不同函数中分别创建了两个Scanner对象,并且在各个函数的结尾使用了close()方法,结果在运行时产生了NoSuchElementException异常. 实验的 ...
- 19南京网络赛B 欧拉降幂
题目链接 给a,b,p.有b个a的幂 #include <iostream> using namespace std; typedef long long LL; const LL N = ...