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 ...
随机推荐
- 菜鸟系列Fabric源码学习 — MVCC验证
Fabric 1.4 源码分析 MVCC验证 读本节文档之前建议先查看[Fabric 1.4 源码分析 committer记账节点]章节. 1. MVCC简介 Multi-Version Concur ...
- Spring 资源注入
Spring开发中经常需要调用各种资源,包含普通文件.网址.配置文件.系统环境变量等,我们可以使用Spring表达式语言(Spring-EL)实现资源的注入. Spring主要使用@Value注解实现 ...
- php strcmp函数漏洞
strcmp函数漏洞 适用5.3版本以前的php 函数作用:字符串比较 要求传入字符串.如果传入非字符串呢? 结果函数报错!但是函数返回“0” . 虽然报错了但函数的判断却是“相等” 如何传入非字符 ...
- 《带你装B,带你飞》pytest修仙之路3 - setup/teardown
1. 简介 学过unittest的都知道里面用前置和后置setup和teardown非常好用,在每次用例开始前和结束后都去执行一次.当然还有更高级一点的setupClass和teardownClass ...
- 文档对象DOM的操作及使用
Dom对象是什么? DOM对象就是每次你打开浏览器后,进入一个网址时浏览器获取到的HTML文本内容,当浏览器获取到HTML文本内容时,会将其内容以DOM对象的形式缓存到内存中,这时你便可以对DOM对象 ...
- JavaScript 继承小记
面向对象编程很重要的一个方面,就是对象的继承.A 对象通过继承 B 对象,就能直接拥有 B 对象的所有属性和方法.这对于代码的复用是非常有用的. 大部分面向对象的编程语言,都是通过“类”(class) ...
- Arrays.asList 返回值类型
public static void main(String[] args) { Integer[] datas = {1,2,3,4,5}; List<Integer> list = A ...
- codevs 3981 动态最大子段和(线段树)
题目传送门:codevs 3981 动态最大子段和 题目描述 Description 题目还是简单一点好... 有n个数,a[1]到a[n]. 接下来q次查询,每次动态指定两个数l,r,求a[l]到a ...
- ACM北大暑期课培训第八天
今天学了有流量下界的网络最大流,最小费用最大流,计算几何. 有流量下界的网络最大流 如果流网络中每条边e对应两个数字B(e)和C(e), 分别表示该边上的流量至少要是B(e),最多 C(e),那么,在 ...
- 原生js面向对象编程-选项卡(点击)
<!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8&quo ...