所谓网络,就是很多电脑相互连接起来所组成的。我们要学网络编程,其实就是编程来实现两个计算机之间通信。
比如,浏览器就使用到网络通信,使得我们的计算机可以和网站服务器通信,获取到我们需要浏览的内容。
又如,qq 让我们可以和好朋友一起交流。以上这些都是使用到了网络编程。
两台电脑通信,那么 数据是如何在两台电脑之间传输的呢? 是的,就是通过网线来传输,通过电的正负来表示 二进制中的 0 1 ,大家都知道在电脑中,一切数据(图像,声音,文字)都是二进制方式存储的,所以这样便可以通过网线传输任何数据。
那我们究竟如何编程实现数据的传输呢?难道用c语言控制电的正负极吗? 当然 我们不需要这样做,我们只需要使用操作系统提供给我们的一套网络编程的api函数即可,什么api函数 其实也就是函数,我们只要学会使用这些函数,那么就可以用来编写出各式各样的网络程序了,不需要我们去做重复造轮子的事情。
接下来就谈谈这一套网络编程的api函数吧。
第一个概念就是 socket ,大家可以点开去百度百科看看,他还附带了一个小例子,最好详细的看看,并尽量试图理解他,这对后面的学习很有帮助。
如何使用这一套编程函数呢?
程序分为服务端和客户端(服务端就相当于我们的网站服务器,客户端就相当于我们的浏览器)
在服务端,我们需要大致按照以下步骤:
1.初始化socket库。
2.绑定本机地址和端口。(服务端特有)
3.监听端口,等待客户端连接。
4.当有客户端连接,进行处理,但后继续监听或者结束程序。
5.退出程序,关闭socket,终止对socket库的使用。
在客户端,我们需要按照以下步骤:
1.初始化socket库。
2.设置远程主机的地址和端口信息,并连接。
3.等待服务端的响应
4.当服务端响应,进行处理。
5.退出程序,关闭socket,终止对socket库的使用
下面摘自一片网友绘制的图:
下面贴出服务器端和客户端的代码:
- 服务端:
#include <stdio.h>
#include <winsock2.h>
#pragma comment(lib, "ws2_32.lib") //此处无分号结尾,用于引入winsock库
int main(void)
{
int len = 0;
WSADATA wd;
int ret = 0;
SOCKET s,c;
char sendBuf[1000]="", recvBuf[1000]="";
SOCKADDR_IN saddr, caddr;
ret = WSAStartup(MAKEWORD(2,2),&wd); /*1.初始化操作*/
if(ret != 0)
{
return 0;
}
if(HIBYTE(wd.wVersion)!=2 || LOBYTE(wd.wVersion)!=2)
{
printf("初始化失败");
WSACleanup();
return 1;
}
s = socket(AF_INET, SOCK_STREAM, 0); /*2.创建服务端socket*/
saddr.sin_addr.S_un.S_addr = htonl(INADDR_ANY); /*3.设置服务端信息*/
saddr.sin_family = AF_INET; /*协议类型*/
saddr.sin_port = htons(8888);
bind(s, (SOCKADDR *)&saddr, sizeof(SOCKADDR)); /*4.绑定在本地端口*/
listen(s,5); /*5.监听端口*/
len = sizeof(SOCKADDR);
while(1)
{
/*6.等待客户端连接,会阻塞在此处,直到有客户端连接到来。*/
c = accept(s, (SOCKADDR*)&caddr, &len);
sprintf(sendBuf, "欢迎光临Alex博客,您的IP:%s\n", inet_ntoa(caddr.sin_addr));
send(c, sendBuf, strlen(sendBuf)+1, 0); /*7.发送数据到客户端*/
recv(c, recvBuf, 1000, 0); /*8.接受客户端的返回*/
printf("%s\n", recvBuf); /*9.打印出客户端发送来的数据*/
closesocket(c); /*10.如果不再跟这个客户端联系,就关闭它*/
}
/*如果有退出循环的条件,这里还需要清除对socket库的使用*/
/* WSACleanup();*/
return 0;
}
- 客户端代码
#include <stdio.h>
#include <winsock2.h>
int main(void)
{
WSADATA wd;
int ret = 0;
SOCKET c;
char recvBuf[1000]="", sendBuf[1000]="";
SOCKADDR_IN saddr;
ret = WSAStartup(MAKEWORD(2,2),&wd); /*1.初始化操作*/
if(ret != 0)
{
return 0;
}
if(HIBYTE(wd.wVersion)!=2 || LOBYTE(wd.wVersion)!=2)
{
printf("初始化失败");
WSACleanup();
return 1;
}
c = socket(AF_INET, SOCK_STREAM, 0); /*2.创建客户端socket*/
saddr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1"); /*3.定义要连接的服务端信息*/
saddr.sin_family = AF_INET;
saddr.sin_port = htons(8888);
connect(c, (SOCKADDR*)&saddr, sizeof(SOCKADDR)); /*4.连接服务端*/
recv(c, recvBuf, 1000, 0);
printf("服务端发来的数据:%s\n", recvBuf);
sprintf(sendBuf, "服务端你好!!!");
send(c, sendBuf, strlen(sendBuf)+1, 0);
closesocket(c);
WSACleanup();
return 0;
}
最后,先运行生成的服务端,然后执行客户端!
执行效果如下: