socket编程入门
来源:互联网 发布:python计算sin 编辑:程序博客网 时间:2024/05/21 09:13
Socket又称"套接字",应用程序通常通过"套接字"向网络发出请求或者应答网络请求。一个Socket由:IP地址+端口号 所组成;
网络层的“ip地址”可以唯一标识网络中的主机,而传输层的“协议+端口”可以唯一标识主机中的应用程序(进程)。这样利用三元组(ip地址,协议,端口)就可以标识网络的进程了,网络中的进程通信就可以利用这个标志与其它进程进行交互。
现在编写两个程序(运行在同一台主机上),一个作为服务器端,一个作为客户端;思路如下:
以下是Windows下的Socket编程,需要的头文件有:
#include<stdio.h>#include<memory.h>#include<WinSock2.h> //Socket所在的头文件但是仅仅包含头文件还不可以,需要把链接文件包含进来:
#pragma comment (lib, "ws2_32.lib")否则程序无法运行!
服务器端:
0.定义两个socket标识:int listenFd,connectFd;一个用于监听是否有客户进行连接,一个用于和客户端进行连接
1.添加以下一个变量以及一个函数:
WSADATA wsaData; WSAStartup(0x0101, &wsaData);WSAStartup函数是为了通知系统调用Socket的Dll(动态链接库文件),故WSAStartup应先于其他的winsock函数
如果不添加该函数,则容易导致程序无法运行;
2.初始化监听套接字:
int listenFd=socket(AF_INET,SOCK_STREAM,0);套接字实际是一个int整型,计算机中很多资源、程序都会用一个int进行表示,例如句柄、进程PID、Linux下的文件表示等(有不懂可以自行Google查阅)
#func解说:int sock=socket( protofamily, type, protocol );
protofamily指定所使用的协议族,对TCP/IP协议族取值为AF_INET。type指定采用的 通信类型:流传输模式取值SOCK-STREAM;报文传输模式取值SOCK-DGRAM。protocol指 定所使用的传输协议,可默认为0;
3.定义服务器的地址用于通信:struct sockaddr_in serverAddr;
sockaddr_in是一个结构体:
struct sockaddr_in {u_char sin_len; /* total length of the address */u_char sin_family; /* family of the address */char sin_port; /* protocol port number */struct in_addr sin_addr; /* IPv4 address of computer *, 通常为INADDR_ANY/char sin_zero[8]; /* not used (set to zero) */};而其中的in_addr也是一个结构体:如下
struct in_addr{ union{ struct{ u_char s_b1, s_b2, s_b3, s_b4;} s_un_b; struct{u_short s_w1,s_w2;} s_un_w; u_long s_addr; } s_un如果看不懂可以暂时忽略,只要记得结构体sockaddr_in用来储存一个服务器或客户端的地址
4.服务器地址serverAddr的初始化:
a.memset初始化为0:memset(&serverAddr,0,sizeof(serverAddr));
b.指定serverAddr的协议族:sin_family赋值为AF_INET(表示TCP/IP);
c.指定serverAddr的源地址:sin_addr.s_addr=htonl(INADDR_ANY);IP地址设置为系统自动获取本机IP地址
d.指定serverAddr的端口:sin_port=htons(PORT);PORT=自定义端口
5.将服务器地址绑定到监听套接字上:
bind(listenFd,(struct sockaddr *)&serverAddr,sizeof(serverAddr);只有进行绑定服务器才会拥有一个地址,客户端才可以连接到服务器
#func解说:bind ( socket, addr, addrlen )
socket是所用套接字的描述符;addr是一个结构,它指定将要赋给套接字的地址;addrlen指出地址的长度。
6.开始监听是否有客户端进行连接:
listen(listenFd,10);
#func解说:listen ( socket, queuesize )
socket是所用套接字的描述符,queuesize指定请求队列的长度。
7.在一个死循环中,如果有客户端连接,则连接套接字进行连接
connectFd=accept(listenFd,(struct sockaddr *)NULL,NULL);
#func解说: accept ( socket, caddress, caddresslen )
socket是所用套接字的描述符;caddress是sockaddr_in结构类型的地址,填入已建立连接的客户地址,caddresslen是指向一个整数的指针,指定地址长度。accept为该连接创建一个新的套接字,并将这个新套接字的描述符返回给调用者。
8.接受客户端传过来的数据:
int n=recv(connectFd,buff,MAXLINE,0);
#func解说:recv ( socket, buffer, length, flags )
socket是所用套接字的描述符, buffer指定用来存放接收数据的内存地址, 1ength指定这个缓冲区的大小,flags允许调用者控制一些细节。
9.向客户端发送回应数据:
send(conncetFd,MESSAGE,Len,0);
#func解说:send ( socket, data, length, flags )
socket是所用套接字的描述符,data是待发送数据在内存中的地址,1ength是一个整数,指定数据的字节数,参数flags包含请求特殊选项的比特位。
10.关闭连接
closesocket(connectFd);closesocket(listenFd);
#func解说:close (socket)
socket是所用套接字的描述符,需要先关闭连接套接字,再关闭监听套接字
完整的代码如下:其中的检测错误下面会进行说明:
#include<stdio.h>#include<memory.h>#include<WinSock2.h>#pragma comment (lib, "ws2_32.lib") #define MPORT 8000#define MAXLEN 2048void main(){char buff[MAXLEN];int listenFd, conncetFd;sockaddr_in serverAddr;WSADATA wsaData;WSAStartup(0x0101, &wsaData);//初始化SocketlistenFd = socket(AF_INET, SOCK_STREAM, 0);if (listenFd < 0){printf("Error at socket():%ld\n", WSAGetLastError());exit(0);}//初始化memset(&serverAddr, 0, sizeof(serverAddr));serverAddr.sin_family = AF_INET;serverAddr.sin_port = htons(MPORT);//设置端口 serverAddr.sin_addr.s_addr =INADDR_ANY;//IP地址设置成INADDR_ANY,让系统自动获取本机的IP地址//将本地地址绑定到所创建的套接字上if (bind(listenFd, (struct sockaddr *)&serverAddr, sizeof(sockaddr)) < 0){printf("Error at bind():%ld\n", WSAGetLastError());exit(0);}//开始监听是否有客户端连接if (listen(listenFd, 10) < 0){printf("Error at listen():%ld\n", WSAGetLastError());exit(0);}printf("=======wait for client=========\n");while (1){//阻塞直到有客户端连接,不然多浪费CPU资源if ((conncetFd = accept(listenFd, (struct sockaddr *)NULL, NULL)) < 0){printf("Error at accept():%ld\n", WSAGetLastError());continue;}//接受客户端传过来的数据int n = recv(conncetFd, buff, MAXLEN, 0);if(n>=0) buff[n] = '\0';printf("%s\n", buff);//向客户端发送回应数据send(conncetFd, "Hello,This message is frome Server\n", 8, 0);closesocket(conncetFd);}closesocket(listenFd);exit(0);}
关于以上的异常判断,每执行一个函数,socket()、bind()、listen()等都会返回一个int整型,如果函数运行出错,则返回-1,成功则会返回一个不同的整数(具体返回的整数可以看上面的#func函数解说);
所以,当函数返回-1的时候,调用该函数WSAGetLastError()可以打印出错信息(一个整型),你可以通过查找该整型得到解决方法
客户端:与服务器端比较类似,如下:
0.定义一个socket标记:int connectFd;
1.添加以下一个变量以及一个函数:WSAStartup应先于其他的winsock函数
WSADATA wsaData;WSAStartup(0x0101, &wsaData)
2.初始化监听套接字:
connectFd=socket(AF_INET,SOCK_STREAM,0);
#func解说:与服务器端相同
3.定义服务器的地址用于通信:struct sockaddr_in serverAddr;
4.服务器地址serverAddr的初始化:
a.memset初始化为0:memset(&serverAddr,0,sizeof(serverAddr));
b.指定serverAddr的协议族:sin_family赋值为AF_INET(TCP/IP);
c.指定serverAddr的源地址:sin_addr.s_addr=inet_addr("127.0.0.1");IP地址设置为本机IP地址
d.指定serverAddr的端口:sin_port=htons(PORT);PORT=自定义端口
5.连接服务器:
connect(connectFd, (struct sockaddr*)&serverAddr, sizeof(serverAddr));
#func解说:与服务器端相同
6.如果连接服务器成功,则可以发送数据:
sendLen = send(connect_sockFd, mess, strlen(mess), 0)
#func解说:返回发送的数据长度(sendLen),与服务器端相同
7.接收数据:
recLen = recv(connectFd, recMessage, MAXLEN, 0)
#func解说:与服务器端相同
8.关闭连接
closesocket(connectFd);
完整代码如下:
#include<stdio.h>#include<WinSock2.h>#include<memory.h>#pragma comment (lib, "ws2_32.lib") #define MPORT 8000#define MAXLEN 2048void main(){int connectFd;char rec[MAXLEN];int len=0;struct sockaddr_in serverAddr;WSADATA wsaData;WSAStartup(0x0101, &wsaData);if ((connectFd = socket(AF_INET, SOCK_STREAM, 0)) < 0){printf("Error at socket():%ld\n", WSAGetLastError());exit(0);}memset(&serverAddr, 0, sizeof(serverAddr)); serverAddr.sin_family = AF_INET; serverAddr.sin_addr.s_addr = inet_addr("127.0.0.1");serverAddr.sin_port = htons(MPORT);if ((connect(connectFd, (struct sockaddr*)&serverAddr, sizeof(serverAddr)) )< 0){printf("Error at connect():%ld\n", WSAGetLastError());exit(0);}printf("conncect succeed\n");int temp;if ((temp = send(connectFd, "Hello world", strlen("Hello world"), 0)) < 0){printf("send error\n");}if ((len = recv(connectFd, rec, MAXLEN, 0) )< 0){printf("Error at recv():%ld\n", WSAGetLastError());exit(0);}rec[len] = '\0';printf("%s\n", rec);closesocket(connectFd);}
- 网络编程入门-socket
- socket编程入门
- socket编程入门
- Socket编程简单入门
- c++ socket编程入门
- linux Socket编程入门
- c++ socket编程入门
- c++ socket编程入门
- VB socket编程入门
- c++ socket编程入门
- Socket编程入门
- Socket编程简单入门
- c++ socket编程入门
- windows socket 编程入门
- Linux socket编程入门
- c++ socket编程入门
- Java Socket编程入门
- socket编程入门
- i os UITableView Cell 机制分析 从用
- SimpleXMLElement 对象相关学习
- Tomcat 支持Linux文件软连接(ln -sf )
- UIWebView 去掉边框的方法
- Android拼图-变形金刚
- socket编程入门
- 全方位的网站推广经验谈
- 新技能get: 订阅Linux内核邮件列表
- iOS MKMapView
- 漫谈程序员系列:无BUG不生活
- 对于QQ三国真的有很多感情在里面
- 排序查找2之中间数的输出
- svn上传.a文件
- python3 多线程爬虫