学习初步练习基于c语言的socket编程
一、理解socket
套接字
应用进程跨网络的通信需要用到socket套接字实现,在TCP/IP协议中,“IP地址+TCP或UDP“唯一的标识了网络通信中的一个进程,这也就叫做一个套接字。套接字产生
引入套接字就不得不介绍一下**系统调用**和**应用编程接口**。当我们有一些特定的应用需要互联网的支持,但这些应用又不能直接使用已经标准化的互联网协议,那么我们应当做哪些工作?大多数操作使用**系统调用**(system call)的机制在应用程序和操作系统之间传递控制权。
当某个应用进程启动系统调用时,控制权就从应用进程传递给系统调用接口。此接口再把控制权传递给操作系统,操作系统把这个调用转给某个内部过程,并执行所请求的操作。内部操作一旦执行完毕,控制权就又通过系统调用接口返回给应用进程。因此,系统调用接口实际上就是应用进程的控制权和操作系统的控制权进行转换的一个接口。由于应用进程在使用系统调用接口之前要编写一些程序,特别是要设置系统调用中的许多参数,因此这种系统调用接口又称为应用编程接口API(Application Programming Interface) 。现在的TCP/IP协议软件已经驻留在操作系统中了。由于TCP/IP协议族被设计成能够运行在多种操作系统的环境中,因此TCP/IP标准没有规定应用程序与TCP/IP协议软件如何接口的细节,而是允许系统设计者能够选择有关API的具体实现细节。目前只有几种可供应用程序使用TCP/IP的应用编程接口API,其中最著名的就是美国加利福尼亚大学伯克利分校为Berkeley UNIX操作系统定义的一种API,它又称为套接字接口(socket interface)。微软在其操作系统中采用了套接字接口API,形成了一个稍有不同的API,并称之为Windows Socket,简称WinSock。(小编在这里只用了微软的)
1.
3.调用socket创建套接字
- 以使用TCP服务为例的系统调用
4.1.建立连接阶段
当套接字被创建后,它的端口号和地址都是空的,进程需要调用Bind来指明套接字本地地址(本地端口号和IP地址)。在服务器端Bind就是把熟知端口号本地IP地址填写到自己创建的套接字里。
服务器调用Bind后还必须调用Listen把套接字设置为被动模式,随时接受客户端服务请求。
服务器紧接着调用accept,把远程客户端发送的连接请求提取出来。此处可以并发,因为处理了多个连接请求。
4.2.数据传送阶段
客户和服务器都在TCP连接上使用send系统调用传送数据,使用recv系统调用接收数据。而各函数的定义可在编译器中具体查看。
4.3.连接释放
客户或服务器结束使用套接字,就把套接字撤销。调用close。
二、具体实现
实现环境:vs2019,c语言,
//server.c端完整代码
#include<stdio.h>
#include<windows.h>
#pragma comment(lib,"ws2_32.lib")SOCKADDR_IN cAddr = { 0 };
int len = sizeof cAddr;
SOCKET clientSocket[1024];
int count = 0;void tonxin(int idx)
{char buff[1024];int r;while (1){r = recv(clientSocket[idx], buff, 1023, NULL);if (r > 0){buff[r] = 0;printf("%d:%s\n", idx, buff);//广播数据for (int i = 0; i < count; i++){send(clientSocket[i], buff, strlen(buff), NULL);}}}
}int main()
{//1请求协议版本WSADATA wsaData;WSAStartup(MAKEWORD(2, 2), &wsaData);if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2){printf("请求协议版本失败!\n");return -1;}printf("请求协议成功!\n");//2创建socketSOCKET serverSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);if (SOCKET_ERROR == serverSocket){printf("创建socket失败!\n");WSACleanup();return -2;}printf("创建socket成功!\n");//3创建协议地址族SOCKADDR_IN addr = { 0 };addr.sin_family = AF_INET;//协议族addr.sin_addr.S_un.S_addr = inet_addr("");//ip地址addr.sin_port = htons(5000);//0-65535端口//4绑定int r = bind(serverSocket, (SOCKADDR*)&addr, sizeof addr);if (-1 == r){printf("bind失败!\n");closesocket(serverSocket);WSACleanup();return -3;}printf("bind成功!\n");//5监听r = listen(serverSocket, 10);//同时最多监听10台if (-1 == r){printf("listen失败!\n");closesocket(serverSocket);WSACleanup();return -2;}printf("listen成功!\n");//6等待客户端连接 while (1){clientSocket[count] = accept(serverSocket, (SOCKADDR*)&cAddr, &len);if (SOCKET_ERROR == clientSocket[count]){printf("服务器宕机!\n");//8关闭socketclosesocket(serverSocket);//9清除协议WSACleanup();return -2;}printf("有客户端连接到服务器了:%s!\n", inet_ntoa(cAddr.sin_addr));//ip地址从整型转换成二进制CreateThread(NULL, NULL, (LPTHREAD_START_ROUTINE)tonxin, (char*)count, NULL, NULL);count++;}//7通信char buff[1024];while (1){r = recv(clientSocket[count], buff, 1023, NULL);if (r > 0){buff[r] = 0;//添加个结束符号\0printf(">>%s\n", buff);}}return 0;
}
- 客户端cilent.c
#include<stdio.h>
#include<windows.h>
#include<graphics.h>
#pragma comment(lib,"ws2_32.lib")//包含socket套接字SOCKET cilentSocket;
HWND hWnd;//在屏幕上显示
int count = 0;void receive()
{char recvBuff[1024];int r;while (1){r = recv(cilentSocket, recvBuff, 1023, NULL);if (r > 0){recvBuff[r] = 0;outtextxy(0, count * 20, recvBuff);//x,y为坐标count++;}}
}
int main()
{//初始化界面hWnd = initgraph(300, 300, SHOWCONSOLE);//init()初始化函数//1请求协议版本WSADATA wsaData;WSAStartup(MAKEWORD(2, 2), &wsaData);if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2){printf("请求协议版本失败\n");return -1;}printf("请求协议版本成功\n");//2创建socket对象cilentSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);if (cilentSocket == SOCKET_ERROR){printf("创建socket失败\n");WSACleanup();return -1;}printf("创建socket成功\n");//3获取协议地址族SOCKADDR_IN addr = { 0 };//初始化addr.sin_family = AF_INET;//协议族addr.sin_addr.S_un.S_addr = inet_addr("");//ip地址addr.sin_port = htons(5000);//端口号0-65535//4连接服务器int r = connect(cilentSocket, (SOCKADDR*)&addr, sizeof addr);if (r == -1){printf("连接服务器失败\n");return -1;}printf("连接服务器成功\n");//5通信char buff[1024];//创建线程CreateThread(NULL, NULL, (LPTHREAD_START_ROUTINE)receive, NULL, NULL, NULL);while (1){memset(buff, 0, 1024);//防止出问题,每次发送前清空一下printf("你想说什么?\n");scanf_s("%s", buff);r = send(cilentSocket, buff, strlen(buff), NULL);}return 0;
}
cilent端的代码在vs2019中有个错误会报出来,不过不用担心,这个错误不是代码错误,而是环境问题,就是在vs2003以后的版本字符集默认是Unicode,只需要在”项目“----”属性“----”高级“----”字符集(Unicode)“改为----”多字节字符集“
即可通过。
运行结果截图类似于如下:
图中表明服务器端确实连到了其它客户端,该图中左边的IP地址填入的应为服务器端IP(小编填的是自己的电脑连的宽度网);而客户端(最好找台另外的电脑,比如说室友的,让他的电脑在vs2019运行cilent.c,你就会很明显的感受到初学时连到情况了。)的IP是客户端自己本机的IP地址。
以上便是小编第一次成功实现socket的情况,初学较浅,望君善待之。
学习初步练习基于c语言的socket编程相关推荐
- Go语言TCP Socket编程
2019独角兽企业重金招聘Python工程师标准>>> Go语言TCP Socket编程 Golang的 主要 设计目标之一就是面向大规模后端服务程序,网络通信这块是服务端 程序必不 ...
- linux c语言 信号,linux下基于C语言的信号编程实例
搜索热词 本文实例讲述了linux下基于C语言的信号编程方法.分享给大家供大家参考.具体如下: #include #include #include #include #include void si ...
- 基于TCP(面向连接)的Socket编程
基于TCP(面向连接)的Socket编程 一.客户端: 1.打开一个套接字(Socket); 2.发起连接请求(connect); 3.如果连接成功,则进行数据交换(read.write.send.r ...
- tcp java实例_实现了基于TCP的Java Socket编程实例代码
实现了基于TCP的Java Socket编程,功能很简单:客户端向服务器端输出一名话"connect",服务器端接收输出到控制台并向客户端输出一名话"Hello" ...
- 基于C语言的软件,基于C语言的计算机软件编程分析
摘 要 C语言是在B语言的基础上发展而来,其功能强大,使用便利,是目前计算机软件编程最基础的语言.C语言有着特殊的编程技巧,他的函数库中包含了编程所需的大部分函数,因此不需要程序员再另外定义:C语言中 ...
- 基于TCP/UDP的socket编程
基于TCP(面向连接)的socket编程 服务器端顺序: 1. 创建套接字(socket) 2. 将套接字绑定到一个本地地址和端口上(bind) 3. 将套接字设为监听模式,准备接收客户请求(l ...
- c语言编写计算机软件,基于C语言的计算机软件编程分析.doc
基于C语言的计算机软件编程分析.doc 基于C语言的计算机软件编程分析 摘要:C语言是一种重要的编程语言,在当今IT业的运用十分广泛.使用C语言来编写的程序简单.直接.准确,极大地推动了计算机软件的更 ...
- java socket 通信协议_java 基于TCP协议的Socket编程和通信
java 基于 TCP 协议的 Socket 编程和通信 在网络通讯中,第一次主动发起通讯的程序被称作客户 端 (Client) 程序, 简称客户端, 而在第一次通讯中等待连接的 程序被称作服务器端 ...
- Sockey编程之基于 UDP 协议的 Socket 编程
一.基于 UDP 协议的 Socket 编程 1.端口选择 已知端口:0~1023,为固定服务保留. 已注册的端口:1024~49151,供普通用户的普通用户进程或程序使用. 动态或私用端口: 491 ...
最新文章
- 图像处理(十二)图像融合(1)Seamless cloning泊松克隆-Siggraph 2004
- 设置textview背景色为透明
- WEBApp-搭建Android开发环境
- boost::hana::on用法的测试程序
- html 和 body标签的 css 设置
- unity socket传输图片_python3实现socket传输图片
- js学习笔记(十一)
- 三维旋转四元数系列(4.四元数三维旋转表达)
- java 工作流_【JAVA之工作流介绍】
- 微软开源软件特征源码分析工具 Application Inspector
- Pycharm连接Mysql问题: Server returns invalid timezone. Go to 'Advanced' tab and set 'serverTimezon
- 69期-Java SE-004_循环、数组-001-002
- 用Arduino+OSC建立一个iPad铁路王国巡视机
- 【STL源码剖析】总结笔记(1):开篇
- 斯坦福机器学习教程学习笔记之1
- win10文件资源管理器打开时很慢
- Java--静态代理和动态代理
- php中怎么添加css样式_html怎么添加css样式?
- Qt音视频开发06-海康sdk内核linux客户端
- 浅谈aps计划排程在3C行业解决方案