http://blog.csdn.net/xluren/article/details/8043484#t15
套接字有三種類型
流式套接字(SOCK_STREAM),數據報套接字(SOCK_DGRAM)及原始套接字。
1.流式套接字提供面向連接、可靠的數據傳輸服務,數據按字節流、按順序收發,保證在傳輸過程中無丟失、無冗余。TCP協議支持該套接字。
2.數據報套接字,提供面向無連接的服務,數據收發無序,不能保證數據的準確到達。UDP協議支持該套接字。
3.原始套接字原始套接字主要用于一些協議的開發,可以進行比較底層的操作。它功能強大,但是沒有上面介紹的兩種套接字使用方便,一般的程序也涉及不到原始套接字。
重要的幾個結構體:
1.sockaddr
- struct?sockaddr??
- {??
- ????????unsigned?short?sa_family;?/*?address族,?AF_xxx?*/??
- ????????char?sa_data[14];?/*?14?bytes的協議地址?*/??
- };??
sa_family 一般來說,都是“AFINET”。
sa_data 包含了一些遠程電腦的地址、端口和套接字的數目,它里面的數據是雜溶在一切的。
由于在設置上面比較麻煩,所以有了一個更清晰的結構體數據
2.struct sockaddr_in
注:“in” 代表 “Internet”
- struct?sockaddr_in???
- {??
- ????????short?int?sin_family;?/*?Internet地址族?*/??
- ????????unsigned?short?int?sin_port;?/*?端口號?*/??
- ????????struct?in_addr?sin_addr;?/*?Internet地址?*/??
- ????????unsigned?char?sin_zero[8];?/*?添0(和struct?sockaddr一樣大小)*/??
- };??
3.struct in_addr (Internet地址)
struct in_addr
{
?unsigned long s_addr;
};
一些函數:
1.socket
#include <sys/types.h>
#include <sys/socket.h>
int socket(int domain , int type , int protocol);
說明:
domain 需要被設置為“AF_INET”;
type為套接字類型;
protocol為協議一般設置為0
2.bind()
#include <sys/types.h>
#include <sys/socket.h>
int bind (int sockfd , struct sockaddr *my_addr , int addrlen) ;
參數說明:
sockfd 是由socket()函數返回的套接字描述符。
my_addr 是一個指向struct sockaddr 的指針,包含有關你的地址的信息:名稱、端口和IP 地址,可以將struct sockaddr_in結構體強制類型轉換傳入。
addrlen 可以設置為sizeof(struct sockaddr)。
3.connect()
#include <sys/types.h>
#include <sys/socket.h>
int connect (int sockfd, struct sockaddr *serv_addr, int addrlen);
參數說明:
sockfd :套接字文件描述符,由socket()函數返回的。
serv_addr 是一個存儲遠程計算機的IP 地址和端口信息的結構。
addrlen 應該是sizeof(struct sockaddr)。
4.listen()
#include <sys/socket.h>
int listen(int sockfd, int backlog);
參數說明:
sockfd 是一個套接字描述符,由socket()系統調用獲得。
backlog 是未經過處理的連接請求隊列可以容納的最大數目。
5.accept()
#include <sys/socket.h>
int accept(int sockfd, void *addr, int *addrlen);
參數說明:
sockfd 是正在listen() 的一個套接字描述符。
addr 一般是一個指向struct sockaddr_in 結構的指針;里面存儲著遠程連接過來的計算機的信息(比如遠程計算機的IP 地址和端口)。
addrlen 是一個本地的整型數值,在它的地址傳給accept() 前它的值應該是sizeof(struct sockaddr_in);accept()不會在addr 中存儲多余addrlen bytes 大小的數據。如果accept()函數在addr 中存儲的數據量不足addrlen,則accept()函數會改變addrlen 的值來反應這個情況。
注:調用成功后返回一個標識符,被send或recv用來進行數據的接收和發送
6.send()
#include <sys/types.h>
#include <sys/socket.h>
int send(int sockfd, const void *msg, int len, int flags);
參數說明:
sockfd 是代表你與遠程程序連接的套接字描述符。
msg 是一個指針,指向你想發送的信息的地址。
len 是你想發送信息的長度。
flags 發送標記。一般都設為0(你可以查看send 的man pages 來獲得其他的參數值并且明白各個參數所代表的含義,很多時候只要你手不懶,通過linux的man命令可以獲得很多詳細的說明,另外很多書籍或者博客信息也都是man的中文翻譯)。
7.recv()
#include <sys/types.h>
#include <sys/socket.h>
int recv(int sockfd, void *buf, int len, unsigned int flags);
參數說明:
sockfd 是你要讀取數據的套接字描述符。
buf 是一個指針,指向你能存儲數據的內存緩存區域。
len 是緩存區的最大尺寸。
flags 是recv() 函數的一個標志,一般都為0
到此你可以寫出一個簡單的c/s模式的通信來了。
c/s模式是面向連接的demo
server端:
- <span?style="font-size:14px;">#include<stdio.h>??
- #include<stdlib.h>??
- #include<string.h>??
- #include<errno.h>??
- #include<sys/types.h>??
- #include<sys/socket.h>??
- #include<netinet/in.h>??
- #define?MAXLINE?4096??
- int?main(int?argc,?char**?argv)??
- {??????
- ????????int????listenfd,?connfd;??????
- ????????struct?sockaddr_in?????servaddr;??????
- ????????char????buff[4096];??????
- ????????int?????n;??????
- ????????if(?(listenfd?=?socket(AF_INET,?SOCK_STREAM,?0))?==?-1?)??
- ????????{??????
- ????????????????printf("create?socket?error:?%s(errno:?%d)\n",strerror(errno),errno);??????
- ????????????????exit(0);??????
- ????????}??????
- ????????memset(&servaddr,?0,?sizeof(servaddr));??????
- ????????servaddr.sin_family?=?AF_INET;??????
- ????????servaddr.sin_addr.s_addr?=?htonl(INADDR_ANY);??????
- ????????servaddr.sin_port?=?htons(6666);??????
- ????????if(?bind(listenfd,?(struct?sockaddr*)&servaddr,?sizeof(servaddr))?==?-1)??
- ????????{??????
- ????????????????printf("bind?socket?error:?%s(errno:?%d)\n",strerror(errno),errno);??????
- ????????????????exit(0);??????
- ????????}??????
- ????????if(?listen(listenfd,?10)?==?-1)??
- ????????{??????
- ????????????????printf("listen?socket?error:?%s(errno:?%d)\n",strerror(errno),errno);??????
- ????????????????exit(0);??????
- ????????}????????
- ????????printf("======waiting?for?client's?request======\n");??????
- ????????while(1)??
- ????????{??????
- ????????????????if(?(connfd?=?accept(listenfd,?(struct?sockaddr*)NULL,?NULL))?==?-1)??
- ????????????????{??????????
- ????????????????????????printf("accept?socket?error:?%s(errno:?%d)",strerror(errno),errno);??????????
- ????????????????????????continue;??????
- ????????????????}??????
- ????????????????n?=?recv(connfd,?buff,?MAXLINE,?0);??????
- ????????????????buff[n]?=?'\0';??????
- ????????????????printf("recv?msg?from?client:?%s\n",?buff);??????
- ????????????????close(connfd);??????
- ????????}??????
- ????????close(listenfd);??
- }</span>??
client端:
- <span?style="font-size:14px;">#include<stdio.h>??
- #include<stdlib.h>??
- #include<string.h>??
- #include<errno.h>??
- #include<sys/types.h>??
- #include<sys/socket.h>??
- #include<netinet/in.h>??
- #define?MAXLINE?4096??
- int?main(int?argc,?char**?argv)??
- {??????
- ????????int????sockfd,?n;??????
- ????????char????recvline[4096],?sendline[4096];??????
- ????????struct?sockaddr_in????servaddr;??????
- ????????if(?argc?!=?2)??
- ????????{??????
- ????????????????printf("usage:?./client?<ipaddress>\n");??????
- ????????????????exit(0);??????
- ????????}??????
- ????????if(?(sockfd?=?socket(AF_INET,?SOCK_STREAM,?0))?<?0)??
- ????????{?????
- ????????????????printf("create?socket?error:?%s(errno:?%d)\n",?strerror(errno),errno);??????
- ????????????????exit(0);??????
- ????????}??????
- ????????memset(&servaddr,?0,?sizeof(servaddr));??????
- ????????servaddr.sin_family?=?AF_INET;??????
- ????????servaddr.sin_port?=?htons(6666);??????
- ????????if(?inet_pton(AF_INET,?argv[1],?&servaddr.sin_addr)?<=?0)??
- ????????{??????
- ????????????????printf("inet_pton?error?for?%s\n",argv[1]);??????
- ????????????????exit(0);??????
- ????????}??????
- ????????if(?connect(sockfd,?(struct?sockaddr*)&servaddr,?sizeof(servaddr))?<?0)??
- ????????{??????
- ????????????????printf("connect?error:?%s(errno:?%d)\n",strerror(errno),errno);??????
- ????????????????exit(0);??????
- ????????}??????
- ????????printf("send?msg?to?server:?\n");?????
- ????????
- ?while(1)
- {
- ??fgets(sendline,?4096,?stdin);?????
- ?if(?send(sockfd,?sendline,?strlen(sendline),?0)?<?0)?????
- ?{??????????
- ?????????printf("send?msg?error:?%s(errno:?%d)\n",?strerror(errno),?errno);?????
- ????????????????exit(0);??????
- ????????} ? ??
- }
- ????????close(sockfd);??????
- ????????exit(0);??
- }??
- </span> ?
- ??fgets(sendline,?4096,?stdin);??????
- ????????if(?send(sockfd,?sendline,?strlen(sendline),?0)?<?0)??????
- ????????{??????
- ????????????????printf("send?msg?error:?%s(errno:?%d)\n",?strerror(errno),?errno);??????
- ????????????????exit(0);??????
- ????????} ? ??