Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1468535
  • 博文数量: 842
  • 博客积分: 12411
  • 博客等级: 上将
  • 技术积分: 5772
  • 用 户 组: 普通用户
  • 注册时间: 2011-06-14 14:43
文章分类

全部博文(842)

文章存档

2013年(157)

2012年(685)

分类: LINUX

2013-03-25 12:55:18

socket操作
1.1 创建socket
int socket(int domain, int type, int protocol);
    domain: 确定通信的特性
                AF_INET          IPv4因特网域
                AF_INET6        IPv6因特网域
                AF_UNIX         UNIX域
                AF_UNSPEC    未指定
            type: 指定套接字的类型
                SOCK_DGRAM        长度固定的、无连接的不可靠报文传递
                SOCK_RAW              IP协议的数据报接口(POSIX.1中可选)
                SOCK_SEQPACKET  长度固定、有序、可靠的面向连接报文传递
                SOCK_STREAM        有序、可靠、双向的面向连接字节流
            protocol参数通常是0,表示按给定的域和套接字类型选择默认协议。当同一域和套接字类型支持多个协议的时候,可以使用protocol参数选择一个特定的协议。
                AF_INET通信域中套接字类型SOCK_STREAM的默认协议是TCP(传输控制协议)
                AF_INET通信与中套接字类型SOCK_DGRAM的默认协议是UDP(用户数据报协议)
1.2 绑定地址(server)
        int bind(int sockfd, const struct sockaddr *my_addr, socklen_t addrlen);
            sockfd: 要绑定的套接字
            my_addr: 地址结构体
            addrlen: 结构体长度,通常为sizeof(my_addr)
        1.2.1 struct sockaddr
            该结构体定义了地址信息
            struct sockaddr_in {
                sa_family_t sin_family;
                in_port_t sin_port;
                struct in_addr sin_addr;
            };
        1.2.2 网络字节转换
            网络中的数据格式为大端,所以需要将小端存储的数据转换成为大端存储,一下为网络字节序和本地字节序(小端)之间转换函数
            uint32_t htonl(uint32_t hostint32);       /// host to net long(uint32_t)
            uint16_t htons(uint16_t hostint16);      /// host to net short(uint16_t)
            uint32_t ntohl(uint32_t netint32);        /// net to host long(uint32_t)
            uint16_t ntohs(uint16_t netint16);       /// net to host short(uint16_t)
        1.2.3 inet_pton
            int inet_pton(int af, const char *src, void *dst);
            将字符串类型的地址转换成为struct sockaddr_in::sin_addr类型
            af: 通信特性
            src: 地址字符串
            dst: truct sockaddr_in::sin_addr类型,长度必需为sizeof(struct in_addr).
       1.2.4 查询地址
            #include
            struct hostent *gethostent(void);    ///(打开主机数据文件)返回struct hostent
            void endhostent(void);    /// 关闭打开的主机数据 文件
            void sethostent(int stayopen); /// 打开主机数据 文件
            struct hostent {
                char *h_name;        /// 主机名
                char **h_aliases;      
                int h_addrtype;
                int h_length;
                char **h_addr_list;
                . . .
            };
            设置地址的例子:
            struct sockaddr_in laddr;
            laddr.sin_family = AF_INET;
            laddr.sin_port = hotns(atoi(SERVERPORT));
            inet_pton(AF_INET, "0.0.0.0", &laddr.sin_addr);
1.3 建立连接(client)
        int connect(int  sockfd , const struct sockaddr*  my_addr , socket_t  addrlen );
        sockfd: 套接字
        my_addr: 想连接的服务器的地址
        addrlen: 地址结构的长度,通常为sizeof(my_addr)
1.4 服务器宣告可以接受连接请求 listen
        int listen(int sockfd, int backlog);
        backlog: 该进程最大的入队连接请求数
1.5 获得连接请求并建立连接 accept
        int accept(int sockfd, struct sockaddr*  my_addr , socket_t  *addrlen );
        my_addr: 用户地址
        addrlen: 用户地址长度
1.6 发数据(client)
        ssize_t send(int sockfd, const void *buf, size_t nbytes, int flags);
        sockfd: 套接字
        buf: 要发送数据的buf
        nbytes: buf长度
        flags: 发送标识
            MSG_DONTROUTE:     勿将数据路由出本地网络
            MSG_DONTWAIT:    允许非阻塞操作
            MSG_EOR:    如果协议支持,此为记录结束
            MSG_OOB:    如果协议支持,发送外带数据
            
1.7 收数据(server)
       ssize_t recv(int sockfd, void *buf, size_t nbytes, int flags);
        sockfd: 套接字
        buf: 接收数据的buf
        nbytes: buf长度
        flags: 发送标识
            MSG_OOB:    如果协议支持,接收外带数据
            MSG_PRRK:    返回报文内容而不真正取走报文
            MSG_TRUNC:    即使报文被截断,要求返回的是报文的实际长度
            MSG_WAITALL:    等待直到所有的数据可用(仅SOCK_STREAM)

mysocket.h

#ifndef MYSOCKET_H_INCLUDED
#define MYSOCKET_H_INCLUDED

#include
#include
#include
#include
#include

#define SERVERPORT "1234"
#define SERVERIP "127.0.0.1"
#define MAXBACKLOG 10
#define MAXIPSIZE 20
#define BUFMAXSIZE 1024*1024
#define WRITEFILEPATH "./recvFile"
#define READFILEPATH "./a.tgz"

using namespace std;

#endif // MYSOCKET_H_INCLUDED


client.cpp

#include "mysocket.h"

int main()
{
int iRet = 0;
int sockFd = 0;
struct sockaddr_in serverAddr;
sockFd = socket(AF_INET, SOCK_STREAM, 0);
char sendBuf[BUFMAXSIZE];
if (sockFd < 0) {
cout << "socket is error" << endl;
} else {
cout << "socket is ok" << endl;
}
serverAddr.sin_family = AF_INET;
serverAddr.sin_port = htons(atoi(SERVERPORT));
inet_pton(AF_INET, SERVERIP, &serverAddr.sin_addr);
iRet = connect(sockFd, (struct sockaddr*)&serverAddr, sizeof(serverAddr));
if (iRet < 0) {
cout << "connect is error." << endl;
} else {
cout << "connect is ok." << endl;
}
FILE *rfp = fopen(READFILEPATH, "rb+");
while(1) {
iRet = fread(sendBuf, 1, BUFMAXSIZE, rfp);
cout << "fork:fread ret = " << iRet << endl;
if (iRet < 0) {
cout << "fread is error" << endl;
break;
}
iRet = send(sockFd, sendBuf, iRet, 0);
if (iRet < BUFMAXSIZE) {
cout << "fread is eof" << endl;
break;
}
}
fclose(rfp);
return 0;
}

server.cpp

#include "mysocket.h"

int main()
{
int iRet = 0;
int sockFd = 0;
struct sockaddr_in serverAddr, clientAddr;
socklen_t clientLen = 0;
char clientIP[MAXIPSIZE];
char recvBuf[BUFMAXSIZE];
sprintf(recvBuf, "rm %s", WRITEFILEPATH);
system(recvBuf);
memset(recvBuf, 0, BUFMAXSIZE);
int recvLen = 0;
FILE *fp = NULL, *wfp = NULL;
sockFd = socket(AF_INET, SOCK_STREAM, 0);   /// create socket
if (sockFd < 0) {
cout << "socket is error" << endl;
} else {
cout << "socket is ok" << endl;
}
serverAddr.sin_family = AF_INET;
serverAddr.sin_port = htons(atoi(SERVERPORT));
inet_pton(AF_INET, "0.0.0.0", &serverAddr.sin_addr);
iRet = bind(sockFd, (struct sockaddr*)&serverAddr, sizeof(serverAddr)); /// bind addr
if (iRet < 0) {
cout << "bind is error." << endl;
} else {
cout << "bind is ok." << endl;
}

iRet = listen(sockFd, MAXBACKLOG);  /// listen
if (iRet < 0) {
cout << "listen is error." << endl;
} else {
cout << "listen is ok." << endl;
}
int newSd;
while(1) {
newSd = accept(sockFd, (struct sockaddr*)&clientAddr, &clientLen);
if (newSd < 0) {
cout << "accept is error : iRet = " << iRet << endl;
break;
}
inet_ntop(AF_INET, &clientAddr.sin_addr, clientIP, MAXIPSIZE);
cout << "client: " << clientIP << " : " << ntohs(clientAddr.sin_port) << " is connected" << endl;

if (fork() == 0) {
wfp = fopen(WRITEFILEPATH, "ab+");
fp = fdopen ( newSd, "r+" );
while (1) {
iRet = fread ( recvBuf, 1, BUFMAXSIZE, fp );
if (iRet <= 0) {
cout << "recv is done" << endl;
break;
}
fwrite(recvBuf, 1, iRet, wfp);
}
fclose(fp);
fclose(wfp);
}
sleep(1);
}

return 0;
}




阅读(681) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~