http://blog.csdn.net/xluren/article/details/8043484#t15
套接字有三種類型
流式套接字(SOCK_STREAM),數據報套接字(SOCK_DGRAM)及原始套接字。
1.流式套接字提供面向連接、可靠的數據傳輸服務,數據按字節流、按順序收發,保證在傳輸過程中無丟失、無冗余。TCP協議支持該套接字。
2.數據報套接字,提供面向無連接的服務,數據收發無序,不能保證數據的準確到達。UDP協議支持該套接字。
3.原始套接字原始套接字主要用于一些協議的開發,可以進行比較底層的操作。它功能強大,但是沒有上面介紹的兩種套接字使用方便,一般的程序也涉及不到原始套接字。
重要的幾個結構體:
1.sockaddr
[cpp]?view plain
?copy struct?sockaddr?? {?? ????????unsigned?short?sa_family;??? ????????char?sa_data[14];??? };??
sa_family 一般來說,都是“AFINET”。
sa_data 包含了一些遠程電腦的地址、端口和套接字的數目,它里面的數據是雜溶在一切的。
由于在設置上面比較麻煩,所以有了一個更清晰的結構體數據
2.struct sockaddr_in
注:“in” 代表 “Internet”
[cpp]?view plain
?copy struct?sockaddr_in??? {?? ????????short?int?sin_family;??? ????????unsigned?short?int?sin_port;??? ????????struct?in_addr?sin_addr;??? ????????unsigned?char?sin_zero[8];??? };??
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端:
[cpp]?view plain
?copy <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端:
[cpp]?view plain
?copy <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);?????? ????????} ? ??
總結
以上是生活随笔為你收集整理的socket通信之最简单的socket通信的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。