一、学习目标
- 了解C语言的socket的概念
- 了解C语言socket的使用方法
- 完成C语言socket服务端
目录
第一篇:(一)脱离学习误区
第二篇:(二)C语言没那么难简单开发带你了解流程
第三篇:(三)轻轻松松理解第一个C语言程序
第四篇:(四)语言的基本数据类型及变量
第五篇:(五)C语言的变量、常量及运算
第六篇:(六)轻轻松松了解C语言的逻辑运算
第七篇:(七)C语言的循环分分钟上手
第八篇:(八)了解基本数组还不是那么简单
第九篇:(九)C语言二维数组与循环嵌套
第十篇:(十)C语言的指针原来是这样
第十一篇:(十一)C语言自定义函数真的很简单
推荐
欢迎大家关注公众号,公众号每满1024及1024倍数则会抽奖赠送机械键盘一份+IT书籍2份哟~
二、了解socket 套接字的使用方法
打个预防针:听不懂概念也会用的,现在不理解以后肯定会理解。若读者是通过我的基础教程开始学到这一篇,我个人建议尽量多熟悉其中知识点再学习socket,socket设计别的知识内容,并且要熟悉基础语法和特性,不然会导致一些问题。若确实学习了有什么问题可以加群问我~
socket也叫做套接字,是在计算机网络中,不同主机监听与发送小心的端点,这个端点是抽象的概念,跟所有不在物理上存在的设计一样,是一中规则下诞生的存在。
2.1 使用socket
以下代码是在网络上找到的代码,自己进行了部分修改。(懒的写了,哈哈哈)这篇内容只注重使用流程,偏向应用,过多的理论知识不再强调。对于新手学习socket我个人建议是先知道如何“掉包”,先做一个“掉包侠”完成了整个流程后才更好的理解其中的问题,而且对于新手来说,一些额外的扩展知识并不是每一个新手都知道的,如果真的需要讲解socket的通信,会设计很多网络层方面的内容,所以我们就先学会如何使用socket,之后再来对这些知识进行梳理。
由于socket的实践内容对于一部分新手步骤过于繁琐,在此则分为上下两片,一篇为服务端,一篇为客户端进行通信,相比各位学习了服务端后再次查看客户端代码会觉得眼前一亮,socket就是用起来麻烦而已嘛~祝各位码运昌隆!
socket是基于TCP/IP的,想必一部分的同学可能对TCP/IP有所耳熟。确实TCP/IP字样在我们学习编程时很常见,他是一种协议,而协议是什么呢?协议是指我们在做某一件事情的时候,我们规定一些细则、标准,方便交流通信,而TCP/IP是协议的一种,再次我们只需要socket是基于TCP/IP协议即可,因为在当前教程中,谈论协议可能对于某一部分读者会有阅读上的障碍,这是很正常的。其实我们在不了解TCP/IP协议的情况下也能进行socket通信,因为我们使用的socket函数是基于TCP/IP的,意思是说我们只需要知道socket如何使用即可。
编写C语言Windows下的socket需要经过几个步骤,首先对WSAStartup 进行初始化,初始化对socket 套接字进行创建,随后配合绑定信息,接着进行配置信息的bind 绑定;绑定了信息后,通过该信息进行isten 监听,监听后若有链接则connect 连接,再接下来开始使用accept 接收请求,得到请求后可以选择接受recv或者send发送数据,最后closesocket 关闭 socket,WSACleanup 最终关闭。
2.2 WSAStartup 初始化
首先对WSAStartup 进行初始化,WSAStartup 方法接收2个参数,1个是WinSock2 的版本号,另一个是WSADATA 的指针。那么我们需要先创建一个WSADATA 类型的对象,代码为:
WSADATA wsaData;
WSADATA 结构用于存储 WSAStartup 初始化后返回的信息,该信息由于使用的是指针,换句话说是传址,那么所存储的信息将会保存在WSAStartup 初始化后。
WSAStartup 接收的第一个参数为版本号,版本号直接可以使用MAKEWORD 生成,MAKEWORd(1, 1)表示选择版本号为1。那么WSAStartup 初始化代码可以写成:
WSAStartup(MAKEWORD(1, 1), &wsaData)
由于WSAStartup等于0则表示初始化失败,初始化失败则退出程序,我们可以写成:
WSADATA wsaData;
if (WSAStartup(MAKEWORD(1, 1), &wsaData) != 0)
{
return 0;
}
2.3 socket创建
socket的创建使用socket方法,socket接收3个参数,分别是IP类型、通信类型、以及最后一个参数可以通过之前传递的参数使用默认类型的配合。IP类型通常使用PF_INET 表示IPV4,通信类型使用TCP,最后一个参数使用0表示通过之前设置的IP类型与通信类型完成匹配的默认选项,代码为:
SOCKET slisten = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
创建完毕后,判断socket是否创建成功,不成功返回-1:
if (slisten == -1)
{
printf("socket error !");
return 0;
}
2.4 IP绑定
接下来开始绑定监听的IP地址。创建sockaddr_in结构体变量。
struct sockaddr_in sin;
随后开始绑定端口、IP类型,其中INADDR_ANY表示本机、6666表示监听端口:
sin.sin_family = AF_INET;
sin.sin_port = htons(8888);
sin.sin_addr.S_un.S_addr = INADDR_ANY;
随后使用bind进行绑定;bind接收3个参数,一个是创建的socket、一个是绑定的IP信息、一个是IP信息的长度,绑定失败则返回-1,代码为:
struct sockaddr_in sin;
sin.sin_family = AF_INET;
sin.sin_port = htons(8888);
sin.sin_addr.S_un.S_addr = INADDR_ANY;
if (bind(slisten, (LPSOCKADDR)&sin, sizeof(sin)) == SOCKET_ERROR)
{
printf("bind error !");
return 0;
}
随后使用listen进行监听,listen接收2个值,一个是socket、一个是队列数量写个10就ok了。代码为:
if (listen(slisten, 5) == SOCKET_ERROR)
{
printf("listen error !");
return 0;
}
2.5 信息接收
accept 接收3个参数,第一个为socket、第二个为 sockaddr变量的指针的指针、第三个为接收sockaddr的长度。代码为:
struct sockaddr_in remoteAddr;
int nAddrlen = sizeof(remoteAddr);
sClient = accept(s, (SOCKADDR *)&remoteAddr, &nAddrlen);
使用accpet后将会进行等待,直到有链接才会执行之后的代码。
随后使用recv接收客户端发送过来的文本信息。recv接收4个参数,第一个是建立的通信、随后是一个数组,接收数据存放的地方、之后会缓存大小,最后一个参数一般设置为0即可。代码为:
char revData[255];
int ret = recv(sClient, revData, 255, 0);
printf(revData);
以上recv函数中,sClient为使用accpet建立的通信,revData为接收信息的缓存区、255为长度。
随后发送一个数据给客户端,用户响应客户端的信息请求。使用send可以往已经建立的通信通道发送数据,send函数接收4个参数,第一个为已经建立的通信、第二个位需要发送的数据、第三个为发送的数据长度、最后一个一般设置为0。代码为:
char * sendData = "你好鸭,我是CSDN 1_bit ,ID是A757291228~\n";
send(sClient, sendData, strlen(sendData), 0);
以上recv函数中,sClient为使用accpet建立的通信,sendData为需要发送的数据、255为长度。
最后调用方法关闭建立的通信即可:
closesocket(sClient);
closesocket(slisten);
WSACleanup();
由于是一次性的通信,程序运行完后则会关闭,在此我们在代码return0前添加停止命令:
system("pause");
所有的依赖引用头文件如下:
#include <winsock2.h>
#include <windows.h>
#include<stdio.h>
#include<stdlib.h>
完整代码如下:
#include <winsock2.h>
#include <windows.h>
#include<stdio.h>
#include<stdlib.h>
int main(int argc, char* argv[])
{
//初始化WSADATA
WSADATA wsaData;
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
{
return 0;
}
//创建scoket
SOCKET slisten = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (slisten == -1)
{
printf("socket error !");
return 0;
}
//绑定端口ip信息
struct sockaddr_in sin;
sin.sin_family = AF_INET;
sin.sin_port = htons(8888);
sin.sin_addr.S_un.S_addr = INADDR_ANY;
if (bind(slisten, (LPSOCKADDR)&sin, sizeof(sin)) == SOCKET_ERROR)
{
printf("bind error !");
return 0;
}
//监听失败则返回
if (listen(slisten, 5) == SOCKET_ERROR)
{
printf("listen error !");
return 0;
}
SOCKET sClient;
struct sockaddr_in remoteAddr;
int nAddrlen = sizeof(remoteAddr);
sClient = accept(slisten, (SOCKADDR *)&remoteAddr, &nAddrlen);
char revData[255];
int ret = recv(sClient, revData, 255, 0);
printf(revData);
//发送信息
char * sendData = "你好鸭,我是CSDN 1_bit ,ID是A757291228~\n";
send(sClient, sendData, strlen(sendData), 0);
closesocket(sClient);
closesocket(slisten);
WSACleanup();
system("pause");
return 0;
}
若使用devc复制代码都报错,则点击编译->编译选项:
随后在出现的窗口中添加如下参数:
总结
1.了解了C语言socket基本编写流程
2.了解了编写C语言Windows下的socket需要经过几个步骤,首先对WSAStartup 进行初始化,初始化对socket 套接字进行创建,随后配合绑定信息,接着进行配置信息的bind 绑定;绑定了信息后,通过该信息进行isten 监听,监听后若有链接则connect 连接,再接下来开始使用accept 接收请求,得到请求后可以选择接受recv或者send发送数据,最后closesocket 关闭 socket,WSACleanup 最终关闭。