linux socket 详解
頭文件:sys/socket.h
相關(guān)結(jié)構(gòu)體:
struct sockaddr
{
??? unsigned short sa_family;?? //地址族
??? char sa_data[14];?? //14字節(jié)協(xié)議地址
};
struct sockaddr_in
{
??? short int sin_family;?? //地址族
??? unsigned short int sin_port;?? //端口號(hào)
??? struct in_addr sin_addr;?? //IP地址
??? unsigned char sin_zero[8];?? //填充0以保持與struct sockaddr同樣大小
};
?
struct in_addr
?{
?? unsigned long s_addr; // that’s a 32-bit long, or 4 bytes
};
注:這兩個(gè)地址類型結(jié)構(gòu)體在頭文件中定義。
相關(guān)函數(shù):
<打開(kāi)套接字>
int socket(int af,int type,int protocol);?? //返回socket套接字,在后面的調(diào)用使用它。
af指定通信發(fā)生區(qū)域(地址族)
UNIX系統(tǒng)有:AF_UNIX,AF_INET,AF_NS等。
DOS、WINDOWS中支持:AF_INET(網(wǎng)際網(wǎng)區(qū)域)
注:地址族與協(xié)議族相同。
type為SOCK_STREAM(建立TCP/IP連接的流式套接字)或SOCK_DGRAM(建立無(wú)連接的UDP數(shù)據(jù)報(bào)套接字)
注:進(jìn)行數(shù)據(jù)報(bào)方式的數(shù)據(jù)傳輸sendto()和recvfrom()時(shí)要用SOCK_DGRAM 不然會(huì)產(chǎn)生錯(cuò)誤。
protocol通常為0
<指定本地地址>
int bind(int sockfd,struct sockaddr *my_addr,int addrlen);
sockfd為socket返回的套接字。
my_addr指向包含本機(jī)IP地址和端口號(hào)等信息的sockaddr類型指針。
addrlen通常為sizeof(struct sockaddr)
注:定義本機(jī)地址通常為
struct sockaddr_in my_addr;
... ...
my_addr.sin_family=AF_INET;?
my_addr.sin_port=htons(指定端口號(hào)); ?? //htons()進(jìn)行字節(jié)順序轉(zhuǎn)換,轉(zhuǎn)換成網(wǎng)絡(luò)字節(jié)優(yōu)先順序。
my_addr.sin_addr.s_addr=INADDR_ANY;?? //INADDR_ANY自動(dòng)獲取本機(jī)IP地址
<監(jiān)聽(tīng)請(qǐng)求>
int listen(int sockfd,int backlog);
backlog指定在請(qǐng)求隊(duì)列中允許的最大請(qǐng)求數(shù),進(jìn)入隊(duì)列的請(qǐng)求將等待accept()它們。
注:服務(wù)器程序的通常執(zhí)行順序?yàn)?sockfd=socket( ... ... );?? bind(sockfd, ..., ...);?? listen(sockfd, ..., ...);
??? ?? 用SOCK_STREAM模式需要 accept()連接請(qǐng)求。
<接受連接請(qǐng)求>
int accept(int sockfd,struct sockaddr * ob_addr,int *addrlen);??? //返回一個(gè)新的套接字,可以通過(guò)該套接字與發(fā)出請(qǐng)求的客戶端進(jìn)行數(shù)據(jù)傳輸。
ob_addr為一個(gè)指向sockaddr類型指針,接受請(qǐng)求后,客戶端的地址信息將保存在*ob_addr中。
addrlen為指向int型的指針,*addrlen值為sizeof(struct sockaddr)。
<請(qǐng)求連接>
int connect(int sockfd,struct sockaddr * ob_addr,int addrlen);?? //向目標(biāo)地址發(fā)送連接請(qǐng)求。
*ob_addr為一個(gè)設(shè)置好的sockaddr類型目標(biāo)地址。
注:通常
struct sockaddr_in ob_addr;
... ...
char ip[20]={"127.0.0.1"};
... ...
ob_addr.sin_family=AF_INET;
ob_addr.sin_addr.s_addr=inet_addr(ip);?? //inet_addr()函數(shù)將名為ip的字符串轉(zhuǎn)化為所需要的ip地址類型。
//相反的 inet_ntoa()函數(shù)可將這種類型轉(zhuǎn)化為字符串類型。如:cout<<inet_ntoa(ob_addr.sin_addr);
ob_addr.sin_port=htons(目標(biāo)端口號(hào));?? //必須對(duì)應(yīng)服務(wù)器監(jiān)聽(tīng)的指定端口,bind和connect中的端點(diǎn)地址必須一樣,客戶端自己的端點(diǎn)地址中端口號(hào)設(shè)置為0,意思是讓系統(tǒng)自動(dòng)選擇端口號(hào)。
<SOCK_STREAM模式數(shù)據(jù)傳輸>
int send(int sockfd,void * buf,int len,int flags);?? //通過(guò)sockfd套接字發(fā)送消息
sockfd為連接上的某套接字。
*buf為要傳輸?shù)臄?shù)據(jù)
len是數(shù)據(jù)長(zhǎng)度(以字節(jié)為單位)。
flags一般為0
int recv(int sockfd,void * buf,int len,int flags);?? //通過(guò)sockfd套接字接受消息并存在*buf中
<SOCK_DGRAM模式數(shù)據(jù)傳輸>
int sendto(int sockfd,void * buf,int len,int flags,struct sockaddr * ob_addr,int addrlen);
ob_addr為sockaddr類型的指針,指向設(shè)置好的目標(biāo)地址。
addrlen常為sizeof(struct sockaddr)
int recvfrom(int sockfd,void *buf, int len,int flags,struct sockaddr * ob_addr,int addrlen);
ob_addr為一個(gè)指向sockaddr類型指針,接受數(shù)據(jù)后,發(fā)送端的地址信息將保存在*ob_addr中。
<關(guān)閉套接字>
bool close(int sockfd);
注:用完了要關(guān)!
本文所用到的其他函數(shù)在netinet/in.h和arpa/inet.h中均可找到。
如果是在windows下,用VC寫(xiě)socket程序,則頭文件為winsock.h。其他函數(shù)基本相同。
可以參考:
《Windows Sockets 網(wǎng)絡(luò)程序設(shè)計(jì)大全》蔣東興等編著 清華大學(xué)出版社
附:
//Linux 下socket通訊 服務(wù)器端設(shè)計(jì)
#include <iostream>
#include <stdlib.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include<string>
#define ListenNum 20
#define BufLen 1024
using namespace std;
int main()
{
??? int sock,sock_new;
??? int buf_len;
??? socklen_t sin_size=sizeof(struct sockaddr);
??? int re,se;
??? char * buf_r=new char [BufLen];
??? char * buf_s=new char [BufLen];
??? struct sockaddr_in my_addr;
??? struct sockaddr_in ob_addr;
??? sock=socket(AF_INET,SOCK_STREAM,0);
??? if(sock==-1) {cout<<"socket error"<<endl;exit(0);}
??? else {cout<<sock<<endl;}
??? my_addr.sin_family=AF_INET;?
??? my_addr.sin_port=htons(3490);
??? my_addr.sin_addr.s_addr=INADDR_ANY;
??? if(bind(sock,(struct sockaddr *)& my_addr,sizeof(struct sockaddr))<0)
??? {
??? ??? cout<<"bind error"<<endl;
??? ??? exit(0);
??? }
??? cout<<"socket port: "<<ntohs(my_addr.sin_port)<<endl;
??? if(listen(sock,ListenNum)<0)
??? {
??? ??? cout<<"listen error"<<endl;
??? ??? exit(0);
??? }
???
??? while(1)
??? {
??? ??? sock_new=accept(sock,(sockaddr *)&ob_addr,&sin_size);
??? ??? if(sock_new<0)
??? ??? {
??? ??? ??? cout<<"accept error"<<endl;
??? ??? ??? exit(0);
??? ??? }
??? ??? else
??? ??? {
??? ??? ??? int p=fork();
??? ??? ??? if(p==0)
??? ??? ??? {
??? ??? ??? ??? cout<<"connect to :"<<inet_ntoa(ob_addr.sin_addr)<<" : "<<htons(ob_addr.sin_port)<<endl;
??? ??? ??? ??? int s=fork();
??? ??? ??? ??? if(s==0)
??? ??? ??? ??? {
??? ??? ??? ??? ??? do
??? ??? ??? ??? ??? {??? ??? ??? ???
??? ??? ??? ??? ??? ??? memset(buf_r,0,sizeof(buf_r));
??? ??? ??? ??? ??? ??? re=recv(sock_new,buf_r,BufLen,0);
??? ??? ??? ??? ??? ??? if(re==-1)
??? ??? ??? ??? ??? ??? {
??? ??? ??? ??? ??? ??? ??? cout<<"recv error"<<endl;
??? ??? ??? ??? ??? ??? ??? exit(0);
??? ??? ??? ??? ??? ??? }
??? ??? ??? ??? ??? ??? else if(re==0)
??? ??? ??? ??? ??? ??? {
??? ??? ??? ??? ??? ??? ??? cout<<inet_ntoa(ob_addr.sin_addr)<<"connection ended"<<endl;
??? ??? ??? ??? ??? ??? ??? close(sock_new);
??? ??? ??? ??? ??? ??? }
??? ??? ??? ??? ??? ??? else
??? ??? ??? ??? ??? ??? {
??? ??? ??? ??? ??? ??? ??? cout<<inet_ntoa(ob_addr.sin_addr)<<" -> "<<buf_r<<endl;
??? ??? ??? ??? ??? ??? }
??? ??? ??? ??? ??? }while(re>0);
??? ??? ??? ??? }
??? ??? ??? ??? else
??? ??? ??? ??? {
??? ??? ??? ??? ??? do
??? ??? ??? ??? ??? {
??? ??? ??? ??? ??? ??? memset(buf_s,0,sizeof(buf_s));
??? ??? ??? ??? ??? ??? cin.getline(buf_s,BufLen);
??? ??? ??? ??? ??? ??? se=send(sock_new,buf_s,BufLen,0);
??? ??? ??? ??? ??? ??? if(se==-1)
??? ??? ??? ??? ??? ??? {
??? ??? ??? ??? ??? ??? ??? cout<<"send error"<<endl;
??? ??? ??? ??? ??? ??? ??? exit(0);
??? ??? ??? ??? ??? ??? }
??? ??? ??? ??? ??? ??? else
??? ??? ??? ??? ??? ??? {
??? ??? ??? ??? ??? ??? ??? cout<<"sended!"<<endl;
??? ??? ??? ??? ??? ??? }
??? ??? ??? ??? ??? }while(1);
??? ??? ??? ??? }
??? ??? ??? }
??? ??? }
??? }???
??? close(sock);
??? return 0;
}
//Linux 下socket通訊 客戶端設(shè)計(jì)
#include <iostream>
#include <stdlib.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string>
#define ListenNum 20
#define BufLen 1024
using namespace std;
int main()
{
???
??? int sock,sock_new;
??? int buf_len;
??? socklen_t sin_size=sizeof(struct sockaddr);
??? char * buf_s=new char [BufLen];
??? char * buf_r=new char [BufLen];
??? char * ip=new char [20];
??? int re;
??? memset(ip,0,sizeof(ip));
??? struct sockaddr_in my_addr;
??? struct sockaddr_in ob_addr;
??? sock=socket(AF_INET,SOCK_STREAM,0);
??? if(sock==-1) {cout<<"socket error"<<endl;exit(0);}
??? else {cout<<sock<<endl;}
??? my_addr.sin_family=AF_INET;?
??? my_addr.sin_port=htons(0);
??? my_addr.sin_addr.s_addr=INADDR_ANY;
??? if(bind(sock,(struct sockaddr *)& my_addr,sin_size)<0)
??? {
??? ??? cout<<"bind error"<<endl;
??? ??? exit(0);
??? }
???
??? cout<<"socket port: "<<ntohs(my_addr.sin_port)<<endl;
??? cout<<"input ip : ";
??? cin.getline(ip,20);
???
??? ob_addr.sin_family=AF_INET;
??? ob_addr.sin_addr.s_addr=inet_addr(ip);
??? ob_addr.sin_port=htons(3490);
??? if(connect(sock,(sockaddr *)&ob_addr,sizeof(sockaddr))<0)
??? {
??? ??? cout<<"connect error"<<endl;
??? ??? exit(0);
??? }
??? else
??? {
??? ??? cout<<"connect success"<<endl;
??? ??? int p=fork();
??? ??? if(p==0)
??? ??? {
??? ??? ??? while(cin.getline(buf_s,BufLen))
??? ??? ??? {
??? ??? ??? ??? if(send(sock,buf_s,BufLen,0)!=-1)
??? ??? ??? ??? ??? cout<<"sended!"<<endl;
??? ??? ??? ??? else cout<<"send error"<<endl;
??? ??? ??? }
??? ??? }
??? ??? else
??? ??? {
??? ??? ??? do
??? ??? ??? {
??? ??? ??? ??? memset(buf_r,0,sizeof(buf_r));
??? ??? ??? ??? re=recv(sock,buf_r,BufLen,0);
??? ??? ??? ??? if(re==-1)
??? ??? ??? ??? {
??? ??? ??? ??? ??? cout<<"recv error"<<endl;
??? ??? ??? ??? ??? exit(0);
??? ??? ??? ??? }
??? ??? ??? ??? else if(re==0)
??? ??? ??? ??? {
??? ??? ??? ??? ??? cout<<inet_ntoa(ob_addr.sin_addr)<<"connection ended"<<endl;
??? ??? ??? ??? ??? close(sock);
??? ??? ??? ??? }
??? ??? ??? ??? else
??? ??? ??? ??? {
??? ??? ??? ??? ??? cout<<inet_ntoa(ob_addr.sin_addr)<<" -> "<<buf_r<<endl;
??? ??? ??? ??? }
??? ??? ??? }while(re>0);
??? ??? }
??? }
??? return 0;
}
總結(jié)
以上是生活随笔為你收集整理的linux socket 详解的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: Cisco热备份路由协议(HSRP) 2
- 下一篇: TrueSec引导的Linux系统和安全