参考资料: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入门学习的更多相关文章

  1. vue入门学习(基础篇)

    vue入门学习总结: vue的一个组件包括三部分:template.style.script. vue的数据在data中定义使用. 数据渲染指令:v-text.v-html.{{}}. 隐藏未编译的标 ...

  2. Hadoop入门学习笔记---part4

    紧接着<Hadoop入门学习笔记---part3>中的继续了解如何用java在程序中操作HDFS. 众所周知,对文件的操作无非是创建,查看,下载,删除.下面我们就开始应用java程序进行操 ...

  3. Hadoop入门学习笔记---part3

    2015年元旦,好好学习,天天向上.良好的开端是成功的一半,任何学习都不能中断,只有坚持才会出结果.继续学习Hadoop.冰冻三尺,非一日之寒! 经过Hadoop的伪分布集群环境的搭建,基本对Hado ...

  4. PyQt4入门学习笔记(三)

    # PyQt4入门学习笔记(三) PyQt4内的布局 布局方式是我们控制我们的GUI页面内各个控件的排放位置的.我们可以通过两种基本方式来控制: 1.绝对位置 2.layout类 绝对位置 这种方式要 ...

  5. PyQt4入门学习笔记(一)

    PyQt4入门学习笔记(一) 一直没有找到什么好的pyqt4的教程,偶然在google上搜到一篇不错的入门文档,翻译过来,留以后再复习. 原始链接如下: http://zetcode.com/gui/ ...

  6. Hadoop入门学习笔记---part2

    在<Hadoop入门学习笔记---part1>中感觉自己虽然总结的比较详细,但是始终感觉有点凌乱.不够系统化,不够简洁.经过自己的推敲和总结,现在在此处概括性的总结一下,认为在准备搭建ha ...

  7. Retrofit 入门学习

    Retrofit 入门学习官方RetrofitAPI 官方的一个例子 public interface GitHubService { @GET("users/{user}/repos&qu ...

  8. MyBatis入门学习教程-使用MyBatis对表执行CRUD操作

    上一篇MyBatis学习总结(一)--MyBatis快速入门中我们讲了如何使用Mybatis查询users表中的数据,算是对MyBatis有一个初步的入门了,今天讲解一下如何使用MyBatis对use ...

  9. opengl入门学习

    OpenGL入门学习 说起编程作图,大概还有很多人想起TC的#include <graphics.h>吧? 但是各位是否想过,那些画面绚丽的PC游戏是如何编写出来的?就靠TC那可怜的640 ...

随机推荐

  1. HDU3555 Bomb 题解 数位DP

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3555 题目大意:求 \([1,n]\) 范围内有多少数包含"49". 解题思路: ...

  2. 「洛谷P3202」[HNOI2010]弹飞绵羊 解题报告

    P3203 [HNOI2010]弹飞绵羊 题目描述 某天,Lostmonkey发明了一种超级弹力装置,为了在他的绵羊朋友面前显摆,他邀请小绵羊一起玩个游戏.游戏一开始,Lostmonkey在地上沿着一 ...

  3. tomcat服务器基本操作:实现www.baidu.com访问tomcat中项目

    0.实现用其他的域名,而不再使用localhost:8080/xxx,访问tomcat中的项目: (1). 修改访问tomcat的端口号: (2). tomcat配置虚拟主机: (3). 本地DNS解 ...

  4. Web漏洞总结: OWASP Top 10

    本文原创,更多内容可以参考: Java 全栈知识体系.如需转载请说明原处. 开发安全 - OWASP Top 10 在学习安全需要总体了解安全趋势和常见的Web漏洞,首推了解OWASP,因为它代表着业 ...

  5. python利用sift和surf进行图像配准

    1.SIFT特征点和特征描述提取(注意opencv版本) 高斯金字塔:O组L层不同尺度的图像(每一组中各层尺寸相同,高斯函数的参数不同,不同组尺寸递减2倍) 特征点定位:极值点 特征点描述:根据不同b ...

  6. FastOne专业计算平台助力生命科学研发

    11月16日,由AWS主办的云计算行业沙龙在中油阳光酒店举行,速石科技CEO陈熹就高性能计算如何助力生命科学领域发表了精彩的演讲. 面临的问题及挑战 在算力及高性能领域,随着行业客户的业务需求量,数据 ...

  7. 【LC_Lesson1】--字符串反转练习

    LeetCode算法练习题目一: 给定一个字符串,要求将该字符串反转后输出 努力学习,天天向上.借助LeetCode的题目,练习编码能力,数据结构,以及C++和Python的编码能力. 一. 算法实现 ...

  8. java 大数的学习

    import java.math.*; import java.util.*; public class study { public static void main(String[] args) ...

  9. Java同步与异步

    一.关键字: thread(线程).thread-safe(线程安全).intercurrent(并发的) synchronized(同步的).asynchronized(异步的). volatile ...

  10. Render函数详解

    一.虚拟dom DOM是文档对象模型(Document Object Model)的简写,在浏览器中通过js来操作DOM的操作性能很差,于是虚拟Dom应运而生.虚拟Dom就是在js中模拟DOM对象树来 ...