Linux网络编程基础(一)
轉(zhuǎn)自:http://blogold.chinaunix.net/u/4502/showart.php?id=13285
初等網(wǎng)絡(luò)函數(shù)介紹(TCP)及示例程序
1、socket?
??? int socket(int domain, int type,int protocol)?
??? domain:說明我們網(wǎng)絡(luò)程序所在的主機(jī)采用的通訊協(xié)族(AF_UNIX和AF_INET等). AF_UNIX只能夠用于單一的Unix系統(tǒng)進(jìn)程間通信,而AF_INET是針對Internet的,因而可以允許在遠(yuǎn)程 主機(jī)之間通信(當(dāng)我們 man socket時發(fā)現(xiàn) domain可選項是 PF_*而不是AF_*,因為glibc是posix的實現(xiàn) 所以用PF代替了AF,不過我們都可以使用的).?
??? type:我們網(wǎng)絡(luò)程序所采用的通訊協(xié)議(SOCK_STREAM,SOCK_DGRAM等) SOCK_STREAM表明我們用的是TCP協(xié)議,這樣會提供按順序的,可靠,雙向,面向連接的比特流. SOCK_DGRAM 表明我們用的是UDP協(xié)議,這樣只會提供定長的,不可靠,無連接的通信.?
??? protocol:由于我們指定了type,所以這個地方我們一般只要用0來代替就可以了 socket為網(wǎng)絡(luò)通訊做基本的準(zhǔn)備.成功時返回文件描述符,失敗時返回-1,看errno可知道出錯的詳細(xì)情況
2、bind?
??? int bind(int sockfd, struct sockaddr *my_addr, int addrlen)?
??? sockfd:是由socket調(diào)用返回的文件描述符.?
??? addrlen:是sockaddr結(jié)構(gòu)的長度.?
??? my_addr:是一個指向sockaddr的指針. 在中有 sockaddr的定義?
??? struct sockaddr{?
????? unisgned short as_family;?
????? char sa_data[14];?
??? };?
??? 不過由于系統(tǒng)的兼容性,我們一般不用這個頭文件,而使用另外一個結(jié)構(gòu)(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設(shè)置為INADDR_ANY表示可以 和任何的主機(jī)通信,sin_port是我們要監(jiān)聽的端口號.sin_zero[8]是用來填充的. bind將本地的端口同socket返回的文件描述符捆綁在一起.成功是返回0,失敗的情況和socket一樣
3、listen?
??? int listen(int sockfd,int backlog)?
??? sockfd:是bind后的文件描述符.?
??? backlog:設(shè)置請求排隊的最大長度.當(dāng)有多個客戶端程序和服務(wù)端相連時, 使用這個表示可以介紹的排隊長度. listen函數(shù)將bind的文件描述符變?yōu)楸O(jiān)聽套接字.返回的情況和bind一樣.
4、accept?
??? int accept(int sockfd, struct sockaddr *addr,int *addrlen)?
??? sockfd:是listen后的文件描述符.???
??? addr,addrlen是用來給客戶端的程序填寫的,服務(wù)器端只要傳遞指針就可以了. bind,listen和accept是服務(wù)器端用的函數(shù),accept調(diào)用時,服務(wù)器端的程序會一直阻塞到有一個 客戶程序發(fā)出了連接. accept成功時返回最后的服務(wù)器端的文件描述符,這個時候服務(wù)器端可以向該描述符寫信息了. 失敗時返回-1.
5、connect?
??? int connect(int sockfd, struct sockaddr * serv_addr,int addrlen)?
??? sockfd:socket返回的文件描述符.?
??? serv_addr:儲存了服務(wù)器端的連接信息.其中sin_add是服務(wù)端的地址?
??? addrlen:serv_addr的長度?
??? connect函數(shù)是客戶端用來同服務(wù)端連接的.成功時返回0,sockfd是同服務(wù)端通訊的文件描述符 失敗時返回-1.
6、程序示例:
/******* 服務(wù)器程序 (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);
??????? }
??????? /* 服務(wù)器端開始建立socket描述符 */?
??????? if((sockfd=socket(AF_INET,SOCK_STREAM,0))==-1)??{
??????????????? fprintf(stderr,"Socket error:%s a",strerror(errno));
??????????????? exit(1);
??????? }
??????? /* 服務(wù)器端填充 sockaddr結(jié)構(gòu) */?
??????? 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);
??????? }
??????? /* 監(jiān)聽sockfd描述符 */?
??????? if(listen(sockfd,5)==-1)? {
??????????????? fprintf(stderr,"Listen error:%s a",strerror(errno));
??????????????? exit(1);
??????? }
??????? while(1)? {
??????????????? /* 服務(wù)器阻塞,直到客戶程序建立連接 */?
??????????????? 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);
??????? }
??????? /*客戶程序填充服務(wù)端的資料*/
??????? 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);
??????? /*客戶程序發(fā)起連接請求*/
??????? 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);
}
編譯產(chǎn)生兩個程序server.o(服務(wù)器端)和client.o(客戶端) 先運(yùn)行./server.o portnumber& (portnumber隨便取一個大于1204且不在/etc/services中出現(xiàn)的號碼 就用8888好了),然后運(yùn)行 ./client.o localhost 8888 看看有什么結(jié)果.
7、總結(jié)?
總的來說網(wǎng)絡(luò)程序是由兩個部分組成的--客戶端和服務(wù)器端.它們的建立步驟一般是:?
服務(wù)器端?
socket-->bind-->listen-->accept?
客戶端?
socket-->connect
總結(jié)
以上是生活随笔為你收集整理的Linux网络编程基础(一)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: (原創) 我有牙周病了 (日記)
- 下一篇: linux 其他常用命令