Socket编程(1)
来源:互联网 发布:c语言函数写法 编辑:程序博客网 时间:2024/05/11 20:31
1、Socket编程的主要步骤与重要函数
Socket编程在windows上首先需要<WinSock2.h>这个头文件和“ws2_32.lib”这个lib库文件。
Soket编程一般分为UDP通信与TCP通信,那么简单的UDP通信与TCP通信前面的过程基本都是一样的,只有在收发数据的时候会有不同。
UDP通信的一般步骤:
(1)、初始化
WSADATA wd;WSAStartup(0x0202,&wd); //初始化加载ws2_32.libWSAStartup是Socket编程的初始化工作
(2)、建立套接字
SOCKET sock = socket(AF_INET,SOCK_DGRAM,0);if(sock == INVALID_SOCKET){cout<<"socket创建失败! 错误码:"<<WSAGetLastError()<<endl;}
SOCKET socket(int af, int type,int protocol);
socke函数是建立套接字,返回一个描述符指向成功的socket。
af : 一般指定为 AF_INET,表示使用UDP,TCP网络
type: 一般分为两类,SOCK_STREAM 表示TCP通信,SOCK_DGRAM表示UDP通信
protocol: 一般设定为0。
(3)、绑定端口
int bind(SOCKET s,const sockaddr* name,int namelen)
bind函数将套接字绑定在指定的端口上,绑定成功返回0,绑定失败返回-1
s: 套接字
name: sockaddr结构体,sockaddr_in与sockaddr可以互相转化,一般常用sockaddr_in,最后再强制转化为sockaddr
sockaddr_in结构体如下
struct sockaddr_in{ short sin_family; unsigned short sin_port; struct in_addr sin_addr; char sin_zero[8];};sin_family: 指定为AF_INET,表示UDP,TCP家族
sin_port: 指定端口
sin_addr: 指定IP
sin_zreo: 保证sockaddr_in与sockaddr有相同的大小,便于相互转化
实例:
const int PORT = 8080;sockaddr_in sa = {AF_INET,htons(PORT)};int n = bind(sock,(sockaddr*)&sa,sizeof(sa));if(SOCKET_ERROR == n){cout<<"bind绑定端口失败! 错误码:"<<WSAGetLastError()<<endl;}套接字绑定了8080端口,其中端口需要用htons反转下,因为网络上的字节序与计算机上的相反,如果是服务器端绑定端口可以不设置IP,这样服务器可以接受本机上所有网段的消息。
(4)、监听
监听只有是TCP服务器端才会有的。
int listen( SOCKET s, int backlog)s: 套接字
backlog: The maximum length of the queue of pending connections.
(5)、等待连接
只有TCP服务器端才会有,服务器端等待客户端的socket连接
SOCKETaccept(SOCKET s,struct sockaddr* addr,int* addrlen);接受成功,则返回一个指向客户段的套接字。
s: 服务器端的套接字
addr: 用于保存客户端的信息(包括:IP,端口等)
addrlen: addr结构体的大小
(6)、连接
只有客户端才会有,向服务器端发送连接请求
intconnect(SOCKET s,const struct sockaddr* name,int namelens: 客户端的套接字
name: 服务器端地址信息(需要制定IP,端口)
namelen: 结构体name的大小
连接成功,则返回非0,否则返回0
(7)、发送数据
发送数据分为UDP发送与TCP发送,UDP发送使用sendto函数,TCP发送使用send函数
intsendto(SOCKET s,const char FAR * buf,int len,int flags,const struct sockaddr FAR * to,int tolen);s: 发送端的套接字
buf: 发送数据的缓存
len: 发送数据的大小
flags: 设为0
to: 接收端的地址信息(需要指定IP,端口)
tolen: 接受端结构体的大小
函数返回实际发送数据的大小
intsend(SOCKET s,const char FAR * buf,int len,int flags);参数: 与senfto类同
(8)、接受数据
接受数据有两个函数,recv 与 recvfrom
intrecv(SOCKET s,char FAR * buf,int len,int flags);s: 接收端(服务器端)的套接字
buf: 接受缓存
len: 缓存大小
flags: 一般设为0
函数返回实际接受的大小,-1表示接受失败
intrecvfrom(SOCKET s,char FAR * buf,int len,int flags,struct sockaddr FAR * from,int FAR * fromlen);from: 发送端的地址信息
fromlen: from结构体的大小
recvfrom 与 recv 最大的区别就是,recvfrom可以获取发送端的地址信息(包括:IP与端口)
(9)、getpeername 与 getsockname
getpeername可以获取对方IP,端口信息(只限TCP)
getsockname可以获取本机IP,端口信息
intgetpeername(SOCKET s,struct sockaddr FAR * name,int FAR * namelen)s: 发送方的套接字
name: 保存发送方的地址信息
namelen: name结构体的大小
intgetsockname(SOCKET s,struct sockaddr FAR * name,int FAR * namelen);s: 本机的套接字
其余:类同
2、示例
UDP通信--发送端
// test_UDP_send.cpp : Defines the entry point for the console application.//#include "stdafx.h"#include <WinSock2.h>#include <iostream>using namespace std;#pragma comment(lib,"ws2_32.lib")int _tmain(int argc, _TCHAR* argv[]){WSADATA wd;WSAStartup(0x0202,&wd);SOCKET sock = socket(AF_INET,SOCK_DGRAM,0);if(sock == INVALID_SOCKET){cout<<"sock 创建失败!"<<endl;return -1;}sockaddr_in sa = {AF_INET,htons(7070)};int n = bind(sock,(sockaddr*)&sa,sizeof(sa));if(n == SOCKET_ERROR){cout<<"bind 失败!"<<endl;return -1;}sockaddr_in accept = {AF_INET,htons(8080)};//指定接受端的端口与IPaccept.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");char s[128];while(1){cout<<"请输入发送的数据: ";gets(s);sendto(sock,s,strlen(s),0,(sockaddr*)&accept,sizeof(accept));}return 0;}
UDP通信--接收端
// test_UDP_recv.cpp : Defines the entry point for the console application.//#include "stdafx.h"#include "stdafx.h"#include <WinSock2.h>#include <iostream>using namespace std;#pragma comment(lib,"ws2_32.lib")int _tmain(int argc, _TCHAR* argv[]){WSADATA wd;WSAStartup(0x0202,&wd);SOCKET sock = socket(AF_INET,SOCK_DGRAM,0);if(sock == INVALID_SOCKET){cout<<"sock 创建失败!"<<endl;return -1;}sockaddr_in sa = {AF_INET,htons(8080)};int n = bind(sock,(sockaddr*)&sa,sizeof(sa)); //绑定了8080端口if(n == SOCKET_ERROR){cout<<"bind 失败!"<<endl;return -1;}char s[128]; //接受数据的缓存n = 0;while((n = recv(sock,s,sizeof(s)-1,0))>0){s[n] = 0;cout<<s<<endl;}return 0;}
TCP通信--服务器端
// test_TCP_server.cpp : Defines the entry point for the console application.//#include "stdafx.h"#include <WinSock2.h>#include <iostream>using namespace std;#pragma comment(lib,"ws2_32.lib")int _tmain(int argc, _TCHAR* argv[]){WSADATA wd;WSAStartup(0x0202,&wd);SOCKET sock = socket(AF_INET,SOCK_STREAM,0);if(sock == INVALID_SOCKET){cout<<"sock 失败!"<<endl;return -1;}sockaddr_in sa = {AF_INET,htons(8080)}; int n = bind(sock,(sockaddr*)&sa,sizeof(sa));if(n == SOCKET_ERROR){cout<<"bind 失败!"<<endl;return -1;}listen(sock,5);//监听SOCKET acceptSock;sockaddr_in client = {0};int nLen = sizeof(client);if((acceptSock = accept(sock,(sockaddr*)&client,&nLen)) == INVALID_SOCKET)//等待连接,会阻塞在这里{cout<<"accept 失败!"<<endl;return -1;}cout<<"有客户端连接:"<<inet_ntoa(client.sin_addr)<<"-"<<htons(client.sin_port)<<endl;char s[128];while((n = recv(acceptSock,s,sizeof(s)-1,0)) > 0 ){s[n] = 0;cout<<s<<endl;}return 0;}
TCP通信--客户端
// test_TCP_client.cpp : Defines the entry point for the console application.//#include "stdafx.h"#include <WinSock2.h>#include <iostream>using namespace std;#pragma comment(lib,"ws2_32.lib")int _tmain(int argc, _TCHAR* argv[]){WSADATA wd;WSAStartup(0x0202,&wd);SOCKET sock = socket(AF_INET,SOCK_STREAM,0);if(sock == INVALID_SOCKET){cout<<"sock 失败!"<<endl;return -1;}sockaddr_in sa = {AF_INET}; //客户端不指定端口,系统会分配一个随机端口int n = bind(sock,(sockaddr*)&sa,sizeof(sa));if(n == SOCKET_ERROR){cout<<"bind 失败!"<<endl;return -1;}sockaddr_in server = {AF_INET,htons(8080)};//指定服务器端的端口与IPserver.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");n = connect(sock,(sockaddr*)&server,sizeof(server));if(n == SOCKET_ERROR){cout<<"连接服务器失败!"<<endl;return -1;}elsecout<<"连接服务器成功!"<<endl;char s[128];while(1){cout<<"请输入发送的数据:";gets(s);send(sock,s,strlen(s),0);}return 0;}
- socket编程(1)
- Socket编程(1)
- Socket编程(1)
- socket网络编程(1)-socket基本概念
- 基于epoll的socket编程(1)------ socket编程基础
- Socket编程原理(1)
- Flash Socket 编程(1)
- Socket编程原理(1)
- Delphi Socket编程(1)
- socket编程复习(1)
- Socket网络编程(1)
- 编程经验:Socket编程Java(1)
- socket编程学习1----socket编程框架
- 网络编程(Socket编程)
- 网络socket编程指南 (转贴)1
- Linux socket编程入门(1)
- C++的Socket编程(1)
- c++ socket编程入门 (1)
- 虚拟机与主机不能ping通的解决方法
- 关于for循环遇到的一些错误
- 2015.08.29,今天开通CSDN博客了!
- Joison博客路之开启篇
- Oracle(四)--> 高级子查询(多例详解难度高,实在不信进来看~)
- Socket编程(1)
- RPG黑暗之光(6)状态栏/技能系统/武器系统/小地图/头像栏
- vector 结构体类型 使用 排序
- MySQL数据类型和常用字段属性总结
- 修改系统tabbar的背景色
- 欢迎使用CSDN-markdown编辑器
- LeetCode(241)Different Ways to Add Parentheses
- maven中net.sf.json报错的解决方法
- 在使用jetty配置jndi的时候报错“Need to specify class name in environment or system property, or as an applet pa