socket网络编程概述
来源:互联网 发布:声音模仿软件 编辑:程序博客网 时间:2024/05/01 20:11
一.套接字的类型
1.流式套接字(SOCK_STREAM)
基于TCP协议实现的。
提供面向连接、可靠的数据传输服务,数据无差错、无重复的发送,且按发送顺序接受。
2.数据报式套接字(SOCK_DGRAM)
基于UDP协议。
提供无连接服务。数据包以独立包形式发送,不提供无错保证,数据可能重复或丢失,并且接受顺序混乱。
3.原始套接字(SOCK_RAM)
二.基于TCP(面向连接)的socket编程
1.服务器端的程序流程
- 创建套接字(socket):该套接字用来监听。
- 将套接字绑定到一个本地地址和端口上(bind)。
- 将套接字设为监听模式,准备接受客户请求(listen)。
- 等待客户请求的到来,当请求到来后,接受连接请求,返回一个新的对应于此次连接的套接字(accept)。
- 用返回的套接字和客户端进行通信(send/recv)。
- 返回,等待另一客户请求。
- 关闭套接字。
总结如下:create socket -> bind -> listen -> accept -> send/recv -> close
2.客户端的程序流程
- 创建套接字(socket)。
- 向服务器发出连接请求(connect)。
- 和服务器进行通信(send/recv)。
- 关闭套接字。
总结如下:create socket -> connect -> send/recv -> close
3.一个基于TCP的socket通信的例子
(1).服务器端(server)
使用2个socket:一个sockSrv,用来监听客户请求,等待客户请求的到来;另一个是sockConn,用来和客户端通信的(发送/接受)。
#include <WinSock2.h>#include <stdio.h>#pragma comment(lib,"ws2_32.lib")void main(){WORD wVersionRequested;WSADATA wsaData;int err;wVersionRequested = MAKEWORD( 1, 1 );err = WSAStartup( wVersionRequested, &wsaData );if ( err != 0 ) {/* Tell the user that we could not find a usable *//* WinSock DLL. */return;}/* Confirm that the WinSock DLL supports 2.2.*//* Note that if the DLL supports versions greater *//* than 2.2 in addition to 2.2, it will still return *//* 2.2 in wVersion since that is the version we *//* requested. */if ( LOBYTE( wsaData.wVersion ) != 1 ||HIBYTE( wsaData.wVersion ) != 1 ) {/* Tell the user that we could not find a usable *//* WinSock DLL. */WSACleanup( );return; }/* The WinSock DLL is acceptable. Proceed. *///create a socket to listenSOCKET sockSrv = socket(AF_INET,SOCK_STREAM,0);SOCKADDR_IN addrSrv;//INADDR_ANY表示IP为0.0.0.0,表示所在机器的所有地址,因为对于多网卡的机器//会有多个IP,那么用0.0.0.0进行socket的bind,则所有网卡都可监听到addrSrv.sin_addr.S_un.S_addr = htonl(INADDR_ANY);addrSrv.sin_family=AF_INET;addrSrv.sin_port=htons(7777);//bind the socketbind(sockSrv,(SOCKADDR*)&addrSrv,sizeof(SOCKADDR));//set the socket to be listening and prepare to receive the client requestlisten(sockSrv , 5 );SOCKADDR_IN addrClient;int len = sizeof(SOCKADDR);while (1){ //wait client request SOCKET sockConn = accept(sockSrv,(SOCKADDR*)&addrClient,&len); char sendBuf[100]= "welcome 11"; sprintf(sendBuf,"Welcome %s to here!",inet_ntoa(addrClient.sin_addr)); //send data send(sockConn,sendBuf,strlen(sendBuf)+1,0); char recvBuf[100]; //receive data recv(sockConn,recvBuf,100,0); printf("%s \n",recvBuf); closesocket(sockConn);}getchar();return;}
(2).客户端(client)
只用一个socket:sockClient,进行通信。
#include <WinSock2.h>#include <stdio.h>#pragma comment(lib,"ws2_32.lib") void main(){WORD wVersionRequested;WSADATA wsaData;int err;wVersionRequested = MAKEWORD(1,1);err = WSAStartup(wVersionRequested,&wsaData);if (err != 0){return;}if (LOBYTE(wsaData.wVersion) != 1 || HIBYTE(wsaData.wVersion) != 1){WSACleanup();return;}//create a socketSOCKET sockClient = socket(AF_INET,SOCK_STREAM,0);SOCKADDR_IN addrSrv;addrSrv.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");//服务器IPaddrSrv.sin_family = AF_INET;addrSrv.sin_port = htons(7777);//send a connect requestconnect(sockClient,(SOCKADDR*)&addrSrv,sizeof(SOCKADDR));//receive datachar recvBuf[100];recv(sockClient,recvBuf,100,0);printf("%s \n",recvBuf);//send datasend(sockClient,"welcome zhaolianxiang",strlen("welcome zhaolianxiang")+1,0);//close socketclosesocket(sockClient);WSACleanup();getchar();}
三.基于UDP(面向无连接)的socket编程
基于UDP的socket编程中,其服务器端和客户端的概念不是很强化。可以把先启动的一端称为接收端(服务器端),发送数据的一端成为发送端(客户端)。
1.服务器端(接收端)的程序流程
- 创建套接字(socket)。
- 将套接字绑定到一个本地地址和端口上(bind)。
- 等待接受数据(recvfrom)。
- 关闭套接字(close)。
总结:create socket -> bind ->recvfrom ->close。
2.客户端(发送端)的程序流程
- 创建套接字(socket)。
- 向服务器发送数据(sendto)。
- 关闭套接字(close)。
总结:create socket ->sendto ->close。
3.一个基于UDP的socket通信的例子
(1).接收端(服务器)
只用一个socket:sockSrv进行通信。
#include <Winsock2.h>#include <stdio.h>#pragma comment(lib,"ws2_32.lib")void main(){WORD wVersionRequested;WSADATA wsaData;int err;wVersionRequested = MAKEWORD( 1, 1 );err = WSAStartup( wVersionRequested, &wsaData );if ( err != 0 ) {return;}if ( LOBYTE( wsaData.wVersion ) != 1 || HIBYTE( wsaData.wVersion ) != 1 ) {WSACleanup( );return; } SOCKET sockSrv=socket(AF_INET,SOCK_DGRAM,0);//创建套接字SOCKADDR_IN addrSrv;addrSrv.sin_addr.S_un.S_addr=htonl(INADDR_ANY);addrSrv.sin_family=AF_INET;addrSrv.sin_port=htons(6000); bind(sockSrv,(SOCKADDR*)&addrSrv,sizeof(SOCKADDR)); //绑定套接字SOCKADDR_IN addrClient;int len=sizeof(SOCKADDR);char recvBuf[100];recvfrom(sockSrv,recvBuf,100,0,(SOCKADDR*)&addrClient,&len);//等待并接受数据printf("%s\n",recvBuf);closesocket(sockSrv);WSACleanup();}
(2).发送端(客户端)
只用一个socket:sockClient进行通信。
#include <Winsock2.h>#include <stdio.h>#pragma comment(lib,"ws2_32.lib")void main(){WORD wVersionRequested;WSADATA wsaData;int err;wVersionRequested = MAKEWORD( 1, 1 );err = WSAStartup( wVersionRequested, &wsaData );if ( err != 0 ) {return;}if ( LOBYTE( wsaData.wVersion ) != 1 || HIBYTE( wsaData.wVersion ) != 1 ) {WSACleanup( );return; }SOCKET sockClient=socket(AF_INET,SOCK_DGRAM,0);SOCKADDR_IN addrSrv;addrSrv.sin_addr.S_un.S_addr=inet_addr("127.0.0.1");//接收方的IPaddrSrv.sin_family=AF_INET;addrSrv.sin_port=htons(6000);sendto(sockClient,"Hello",strlen("Hello")+1,0,(SOCKADDR*)&addrSrv,sizeof(SOCKADDR));//发送数据closesocket(sockClient); //关闭套接字WSACleanup();}
四.TCP socket和UDP socket的比较
TCP socket模式:C/S模式,即客户端/服务器端。适用于一个server,多个client,即一对多。使用send/recv函数发送和接受数据。
UDP socket模式:发送端/接收端模式,即先启动的一端为接收端。适用于一对一的情况,比如聊天。即client <----> client。使用sendto/recvfrom函数发送和接受数据。
五.一个基于UDP的简单聊天程序
(1).服务器端
#include <WinSock2.h>#include <stdio.h>#pragma comment(lib,"ws2_32.lib")void main(){WORD wVersionRequested;WSAData wsaData;int err;wVersionRequested = MAKEWORD(2,2);err = WSAStartup(wVersionRequested,&wsaData);if (err != 0){return;}if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2){WSACleanup();return;}//create a socketSOCKET sockSrv = socket(AF_INET,SOCK_DGRAM,0);SOCKADDR_IN addrSrv;addrSrv.sin_addr.S_un.S_addr = htonl(INADDR_ANY);addrSrv.sin_family = AF_INET;addrSrv.sin_port = htons(5555);//bind the socketbind(sockSrv,(SOCKADDR*)&addrSrv,sizeof(SOCKADDR));char recvBuf[1000];char sendBuf[1000];char tempBuf[1000];SOCKADDR_IN addrClient;int len = sizeof(SOCKADDR);while (1){//receive datarecvfrom(sockSrv,recvBuf,100,0,(SOCKADDR*)&addrClient,&len);if ('q' == recvBuf[0]){sendto(sockSrv,"q",strlen("q")+1,0,(SOCKADDR*)&addrClient,len);printf("chat end!\n");break;}sprintf(tempBuf,"%s say: %s",inet_ntoa(addrClient.sin_addr),recvBuf);printf("%s \n",tempBuf);//send dataprintf("pls input data:\n");gets(sendBuf);sendto(sockSrv,sendBuf,strlen(sendBuf)+1,0,(SOCKADDR*)&addrClient,len);}closesocket(sockSrv);WSACleanup();getchar();};
分析:服务器端(接收端)是先接受数据,再发送数据。只有一个socket对象用来通信:sockSrv,。
(2).客户端
#include <WinSock2.h>#include <stdio.h>#pragma comment(lib,"ws2_32.lib")void main(){WORD wVersionRequested;WSAData wsaData;int err;wVersionRequested = MAKEWORD(2,2);err = WSAStartup(wVersionRequested,&wsaData);if (err != 0){return;}if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2){WSACleanup();return;}SOCKET sockClient = socket(AF_INET,SOCK_DGRAM,0);SOCKADDR_IN addrSrv;addrSrv.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");addrSrv.sin_family = AF_INET;addrSrv.sin_port = htons(5555);int len = sizeof(SOCKADDR);char recvBuf[100];char sendBuf[100];char tempBuf[100];while (1){printf("pls input data:\n");gets(sendBuf);sendto(sockClient,sendBuf,strlen(sendBuf)+1,0,(SOCKADDR*)(&addrSrv),len);recvfrom(sockClient,recvBuf,100,0,(SOCKADDR*)&addrSrv,&len);if ('q' == recvBuf[0]){sendto(sockClient,"q",strlen("q")+1,0,(SOCKADDR*)&addrSrv,len);printf("chat end!\n"); break;}sprintf(tempBuf,"%s says: %s",inet_ntoa(addrSrv.sin_addr),recvBuf);printf("%s \n",tempBuf);}closesocket(sockClient);WSACleanup();getchar();};分析:客户端(发送端)是先发送数据,后接受数据。只用一个socket:sockClient进行通信。
- socket网络编程概述
- 《unix网络编程》(7)socket概述
- linux网络编程之 ─── socket概述
- 网络编程Socket之UDP(一)UDP概述
- 网络编程Socket之TCP之select概述
- linux网络编程之 ─── socket概述
- Socket编程原理概述
- socket编程概述
- UNIX SOCKET编程概述
- Socket编程原理概述
- socket网络编程之路 第四篇 ------winsock网络编程模型(1)之概述
- linux网络编程之socket(一):socket概述和字节序、地址转换函数
- linux网络编程之socket(一):socket概述和字节序、地址转换函数
- linux网络编程之socket(一):socket概述和字节序、地址转换函数
- linux网络编程之socket(一):socket概述和字节序、地址转换函数
- linux网络编程之socket(一):socket概述和字节序、地址转换函数
- linux网络编程之socket(一):socket概述和字节序、地址转换函数
- linux网络编程之socket(一):socket概述和字节序、地址转换函数
- IOS对象复制问题
- 一位强人写的电子工程师起码技术要求
- 闭着眼睛也要会打的【数据的输入和输出有几道练习题】---- HDU1089-1096
- X264编码流程详解
- HTTP 无法注册 URL http://127.0.0.1:9999/calculatorservice/metadata。进程不具有此命名空间的访问权限
- socket网络编程概述
- Android小应用:智能情景模式
- 网络拥塞控制(八) 外传之如何测量TCP的拥塞窗口
- 网络拥塞控制(九) CUBIC
- 对信号量的理解
- 网络拥塞控制(十) 总结
- linux命令--grep 的用法
- How to Perfectly Uninstall STOPzilla
- struts2环境配置