Linux网络编程基础(一)
轉自:http://blogold.chinaunix.net/u/4502/showart.php?id=13285
初等網絡函數介紹(TCP)及示例程序
1、socket?
??? int socket(int domain, int type,int protocol)?
??? domain:說明我們網絡程序所在的主機采用的通訊協族(AF_UNIX和AF_INET等). AF_UNIX只能夠用于單一的Unix系統進程間通信,而AF_INET是針對Internet的,因而可以允許在遠程 主機之間通信(當我們 man socket時發現 domain可選項是 PF_*而不是AF_*,因為glibc是posix的實現 所以用PF代替了AF,不過我們都可以使用的).?
??? type:我們網絡程序所采用的通訊協議(SOCK_STREAM,SOCK_DGRAM等) SOCK_STREAM表明我們用的是TCP協議,這樣會提供按順序的,可靠,雙向,面向連接的比特流. SOCK_DGRAM 表明我們用的是UDP協議,這樣只會提供定長的,不可靠,無連接的通信.?
??? protocol:由于我們指定了type,所以這個地方我們一般只要用0來代替就可以了 socket為網絡通訊做基本的準備.成功時返回文件描述符,失敗時返回-1,看errno可知道出錯的詳細情況
2、bind?
??? int bind(int sockfd, struct sockaddr *my_addr, int addrlen)?
??? sockfd:是由socket調用返回的文件描述符.?
??? addrlen:是sockaddr結構的長度.?
??? my_addr:是一個指向sockaddr的指針. 在中有 sockaddr的定義?
??? struct sockaddr{?
????? unisgned short as_family;?
????? char sa_data[14];?
??? };?
??? 不過由于系統的兼容性,我們一般不用這個頭文件,而使用另外一個結構(struct sockaddr_in) 來代替.在中有sockaddr_in的定義?
??? struct sockaddr_in{?
????? unsigned short sin_family;?
????? unsigned short int sin_port;?
????? struct in_addr sin_addr;?
????? unsigned char sin_zero[8];?
??? 我們主要使用Internet所以sin_family一般為AF_INET,sin_addr設置為INADDR_ANY表示可以 和任何的主機通信,sin_port是我們要監聽的端口號.sin_zero[8]是用來填充的. bind將本地的端口同socket返回的文件描述符捆綁在一起.成功是返回0,失敗的情況和socket一樣
3、listen?
??? int listen(int sockfd,int backlog)?
??? sockfd:是bind后的文件描述符.?
??? backlog:設置請求排隊的最大長度.當有多個客戶端程序和服務端相連時, 使用這個表示可以介紹的排隊長度. listen函數將bind的文件描述符變為監聽套接字.返回的情況和bind一樣.
4、accept?
??? int accept(int sockfd, struct sockaddr *addr,int *addrlen)?
??? sockfd:是listen后的文件描述符.???
??? addr,addrlen是用來給客戶端的程序填寫的,服務器端只要傳遞指針就可以了. bind,listen和accept是服務器端用的函數,accept調用時,服務器端的程序會一直阻塞到有一個 客戶程序發出了連接. accept成功時返回最后的服務器端的文件描述符,這個時候服務器端可以向該描述符寫信息了. 失敗時返回-1.
5、connect?
??? int connect(int sockfd, struct sockaddr * serv_addr,int addrlen)?
??? sockfd:socket返回的文件描述符.?
??? serv_addr:儲存了服務器端的連接信息.其中sin_add是服務端的地址?
??? addrlen:serv_addr的長度?
??? connect函數是客戶端用來同服務端連接的.成功時返回0,sockfd是同服務端通訊的文件描述符 失敗時返回-1.
6、程序示例:
/******* 服務器程序 (server.c) ************/?
#include "stdio.h"
#include "stdlib.h"
#include "errno.h"
#include "sys/types.h"
#include "sys/socket.h"
#include "unistd.h"
#include "netinet/in.h"
#include "netdb.h"
int main(int argc,char *argv[])
{
??????? int sockfd,new_fd;
??????? struct sockaddr_in server_addr;
??????? struct sockaddr_in client_addr;
??????? int sin_size,portnumber;
??????? char hello[]="Hello! Are You Fine? ";
??????? if ( argc!=2 )? {
??????????????? fprintf(stderr,"Usage:%s portnumbera ",argv[0]);
??????????????? exit(1);
??????? }
??????? if((portnumber=atoi(argv[1]))<0)? {
??????????????? fprintf(stderr,"Usage:%s portnumbera ",argv[0]);
??????????????? exit(1);
??????? }
??????? /* 服務器端開始建立socket描述符 */?
??????? if((sockfd=socket(AF_INET,SOCK_STREAM,0))==-1)??{
??????????????? fprintf(stderr,"Socket error:%s a",strerror(errno));
??????????????? exit(1);
??????? }
??????? /* 服務器端填充 sockaddr結構 */?
??????? bzero(&server_addr,sizeof(struct sockaddr_in));?
??????? server_addr.sin_family=AF_INET;
??????? server_addr.sin_addr.s_addr=htonl(INADDR_ANY);
??????? server_addr.sin_port=htons(portnumber);
??????? /* 捆綁sockfd描述符 */?
??????? if(bind(sockfd,(struct sockaddr *)(&server_addr),sizeof(struct sockaddr))==-1)? {
??????????????? fprintf(stderr,"Bind error:%s a",strerror(errno));
??????????????? exit(1);
??????? }
??????? /* 監聽sockfd描述符 */?
??????? if(listen(sockfd,5)==-1)? {
??????????????? fprintf(stderr,"Listen error:%s a",strerror(errno));
??????????????? exit(1);
??????? }
??????? while(1)? {
??????????????? /* 服務器阻塞,直到客戶程序建立連接 */?
??????????????? sin_size=sizeof(struct sockaddr_in);
??????????????? if((new_fd=accept(sockfd,(struct sockaddr *)(&client_addr),&sin_size))==-1)? {
??????????????????????? fprintf(stderr,"Accept error:%s a",strerror(errno));
??????????????????????? exit(1);
??????????????? }
??????????????? fprintf(stderr,"Server get connection from %s ",inet_ntoa(client_addr.sin_addr));
??????????????? if(write(new_fd,hello,strlen(hello))==-1)? {
??????????????????????? fprintf(stderr,"Write Error:%s ",strerror(errno));
??????????????????????? exit(1);
??????????????? }
??????????????? close(new_fd);
??????? }
??????? close(sockfd);
??????? exit(0);
}
/*******客戶端程序 client.c*********/
#include "stdio.h"
#include "stdlib.h"
#include "errno.h"
#include "sys/types.h"
#include "sys/socket.h"
#include "unistd.h"
#include "netinet/in.h"
#include "netdb.h"
int main(int argc, char *argv[])
{
??????? int sockfd;
??????? char buffer[1024];
??????? struct sockaddr_in server_addr;
??????? struct hostent *host;
??????? int portnumber,nbytes;
??????? if(argc!=3) {
??????????????? fprintf(stderr,"Usage:%s hostname portnumbera ",argv[0]);
??????????????? exit(1);
??????? }
??????? if((host=gethostbyname(argv[1]))==NULL) {
??????????????? fprintf(stderr,"Gethostname error ");
??????????????? exit(1);
??????? }
??????? if((portnumber=atoi(argv[2]))<0) {
??????????????? fprintf(stderr,"Usage:%s hostname portnumbera ",argv[0]);
??????????????? exit(1);
??????? }
??????? /*客戶程序開始建立 sockfd描述符*/
??????? if((sockfd=socket(AF_INET,SOCK_STREAM,0))==-1) {
??????????????? fprintf(stderr,"Socket Error:%sa ",strerror(errno));
??????????????? exit(1);
??????? }
??????? /*客戶程序填充服務端的資料*/
??????? bzero(&server_addr,sizeof(server_addr));
??????? server_addr.sin_family=AF_INET;
??????? server_addr.sin_port=htons(portnumber);
??????? server_addr.sin_addr=*((struct in_addr *)host->h_addr);
??????? /*客戶程序發起連接請求*/
??????? if(connect(sockfd,(struct sockaddr *)(&server_addr),sizeof(struct sockaddr))==-1) {
??????????????? fprintf(stderr,"Connect Error:%sa ",strerror(errno));
??????????????? exit(1);
??????? }
??????? if((nbytes=read(sockfd,buffer,1024))==-1) {
??????????????? fprintf(stderr,"Read Error:%s ",strerror(errno));
??????????????? exit(1);
??????? }
??????? buffer[nbytes]='';
??????? printf("I have received:%s ",buffer);
??????? close(sockfd);
??????? exit(0);
}
編譯產生兩個程序server.o(服務器端)和client.o(客戶端) 先運行./server.o portnumber& (portnumber隨便取一個大于1204且不在/etc/services中出現的號碼 就用8888好了),然后運行 ./client.o localhost 8888 看看有什么結果.
7、總結?
總的來說網絡程序是由兩個部分組成的--客戶端和服務器端.它們的建立步驟一般是:?
服務器端?
socket-->bind-->listen-->accept?
客戶端?
socket-->connect
總結
以上是生活随笔為你收集整理的Linux网络编程基础(一)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: (原創) 我有牙周病了 (日記)
- 下一篇: Delphi识别读取验证码