Linux网络编程(一)

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网络编程(一),布布扣,bubuko.com

时间: 2024-11-03 21:47:46

Linux网络编程(一)的相关文章

linux网络编程-(socket套接字编程UDP传输)

今天我们来介绍一下在linux网络环境下使用socket套接字实现两个进程下文件的上传,下载,和退出操作! 在socket套接字编程中,我们当然可以基于TCP的传输协议来进行传输,但是在文件的传输中,如果我们使用TCP传输,会造成传输速度较慢的情况,所以我们在进行文件传输的过程中,最好要使用UDP传输. 在其中,我们需要写两个程序,一个客户端,一个服务端,在一个终端中,先运行服务端,在运行客户端,在服务端和客户端都输入IP地址和端口号,注意服务端和客户端的端口号要相同,然后选择功能,在linux

Linux网络编程socket选项之SO_LINGER,SO_REUSEADDR

from http://blog.csdn.net/feiyinzilgd/article/details/5894300 Linux网络编程中,socket的选项很多.其中几个比较重要的选项有:SO_LINGER(仅仅适用于TCP,SCTP), SO_REUSEADDR. SO_LINGER 在默认情况下,当调用close关闭socke的使用,close会立即返回,但是,如果send buffer中还有数据,系统会试着先把send buffer中的数据发送出去,然后close才返回. SO_L

很全的linux网络编程技巧

注:作者王晓,本人认为总结得很好,故记之,绝无侵权之意. 1. LINUX网络编程基础知识 1 1.1. TCP/IP协议概述 1 1.2. OSI参考模型及TCP/IP参考模型 1 1.3. TCP协议 3 1.4. UDP协议 5 1.5. 协议的选择 6 2. 网络相关概念 6 2.1. socket概念 7 2.2. socket类型 8 2.3. socket信息数据结构 8 2.4. 数据存储优先顺序的转换 8 2.5. 地址格式转化 9 2.6. 名字地址转化 10 3. sock

linux网络编程 no route to host 解决方案

linux网络编程 no route to host 解决方案 [整合资料] (2013-05-13 21:38:12) 转载▼ 标签: net iptables it 分类: Linux 参考资料http://1413570.blog.51cto.com/1403570/792861http://2614223.blog.51cto.com/2604223/764757 在vmvare里面配了两台mysql,发现用mysql连不上mysql服务器,用telnet登录mysql的3306端口,发

Linux网络编程

第二章 Linux网络编程 2.1客户——服务器模型 目前大多数网络应用程序在编写时都采用客户—服务器模型,假设一端是客户,另一端是服务器,让服务器提供给客户一定的服务内容.它要求有一方(服务器方)在启动执行程序后(无限期地)等待其他客户端程序与之通信.这里可以再分为两种具体类型:并发型交互与重复型交互. (1)并发型交互.在并发型交互模式下,程序的主要运作步骤如下: ·等待一个客户请求的到来: ·生成一个新的进程或者任务来处理这个客户请求,同时这里还可以接收其他客户的请求,处理结束后,终止这个

Linux网络编程10&mdash;&mdash;使用UDP实现五子棋对战

思路 1. 通信 为了同步双方的棋盘,每当一方在棋盘上落子之后,都需要发送给对方一个msg消息,让对方知道落子位置.msg结构体如下: /* 用于发给对方的信息 */ typedef struct tag_msg { int msg_type; /* 悔棋? */ int msg_color; int msg_row; int msg_col; }MSG, *pMSG; 2. 悔棋 用链表头插法来模拟栈,链表记录了双方下子的轨迹.结构如下: /* 记录每一步的轨迹 */ typedef stru

linux网络编程学习笔记之二 -----错误异常处理和各种碎碎(更新中)

errno 在unix系统中对大部分系统调用非正常返回时,通常返回值为-1,并设置全局变量errno(errno.h),如socket(), bind(), accept(), listen().erron存放一个正整数来保存上次出错的错误值. 对线程而言,每个线程都有专用的errno变量,不必考虑同步问题. strerror converts to English (Note: use strerror_r for thread safety) perror is simplified str

linux网络编程笔记——TCP

1.TCP和UDP TCP是长连接像持续的打电话,UDP是短消息更像是发短信.TCP需要消耗相对较多的资源,但是传输质量有保障,UDP本身是不会考虑传输质量的问题. 2.网络传输内容 我习惯的做法是直接通过TCP传送结构体,当然前提是收发两端都在程序里对目标结构体有充分的定义.特别说明的一点是,要小心收发两端处理器的大小端问题!而且传输信息头里必须包含长度信息,而且通用的是大端.但是,这里的长度和结构体,我选择用小端进行传输. 3.TCPserver实现 参考了别人多线程的回调写法,看起来不错.

Linux网络编程——tcp并发服务器(poll实现)

想详细彻底地了解poll或看懂下面的代码请参考<Linux网络编程--I/O复用之poll函数> 代码: #include <string.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <sys/select.h> #include <sys/time.h> #include <sys/socket.h> #incl