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用来储存一个服务器或客户端的地址
bind(listenFd,(struct sockaddr *)&serverAddr,sizeof(serverAddr);只有进行绑定服务器才会拥有一个地址,客户端才可以连接到服务器
listen(listenFd,10);
connectFd=accept(listenFd,(struct sockaddr *)NULL,NULL);
int n=recv(connectFd,buff,MAXLINE,0);
send(conncetFd,MESSAGE,Len,0);
closesocket(connectFd); closesocket(listenFd);
完整的代码如下:其中的检测错误下面会进行说明:
#include<stdio.h> #include<memory.h> #include<WinSock2.h> #pragma comment (lib, "ws2_32.lib") #define MPORT 8000 #define MAXLEN 2048 void main(){ char buff[MAXLEN]; int listenFd, conncetFd; sockaddr_in serverAddr; WSADATA wsaData; WSAStartup(0x0101, &wsaData); //初始化Socket listenFd = 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)
connectFd=socket(AF_INET,SOCK_STREAM,0);
connect(connectFd, (struct sockaddr*)&serverAddr, sizeof(serverAddr));
sendLen = send(connect_sockFd, mess, strlen(mess), 0)
recLen = recv(connectFd, recMessage, MAXLEN, 0)
closesocket(connectFd);
#include<stdio.h> #include<WinSock2.h> #include<memory.h> #pragma comment (lib, "ws2_32.lib") #define MPORT 8000 #define MAXLEN 2048 void 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); }
原文地址:http://blog.csdn.net/u012336923/article/details/40920897