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