Linux套接字编程指南:掌握Socket使用技巧 (linux socket 使用)

Linux作为一款广泛使用的操作系统,其受欢迎程度主要归功于它的稳定性、高度的可定制化和丰富的开源软件库。在Linux下,套接字(Socket)是一种常见的网络编程模型,它允许不同的应用程序之间在网络上进行通信。本文将介绍Linux套接字编程的基础知识,并提供一些用于掌握Socket使用技巧的实用提示。

什么是Linux套接字编程?

Linux套接字编程是一种基于Socket API的网络编程,使用Linux中提供的套接字接口来连接和通信不同的应用程序。在这种编程模型中,应用程序可以充当以下两种角色之一:

1.服务器:服务器程序在一个指定的端口监听传入的连接请求,并处理这些请求。例如,Web服务器可以监听标准HTTP端口(80),而数据库服务器可以监听标准MySQL端口(3306)。

2.客户端:客户端程序与特定端口上的服务器建立连接,并向服务器发送请求。例如,Web浏览器可以通过HTTP协议与Web服务器建立连接并获取网页,而数据库客户端可以通过MySQL协议连接到MySQL服务器以读写数据库。

在Linux套接字编程中,Socket API提供了一组函数用于创建、绑定、监听、连接和发送/接收数据。以下是一些常用的Socket API函数:

• socket():创建一个套接字

• bind():绑定IP地址和端口号

• listen():开始监听传入的连接请求

• accept():接受传入的连接请求并返回一个新的套接字

• connect():与已知IP地址和端口号的主机建立连接

• send():发送数据到另一个套接字

• recv():从另一个套接字接收数据

掌握Linux套接字编程的技巧

以下是一些掌握Linux套接字编程的技巧,可以帮助开发人员写出更高效、更健壮的网络应用程序。

1.适当设置套接字选项

在Linux套接字编程中,可以使用setsockopt()函数设置套接字选项。下面是一些设置套接字选项的一些例子:

• SO_REUSEADDR:允许多个套接字绑定相同的IP地址和端口号。

• SO_KEEPALIVE:启用TCP心跳功能,当连接处于空闲状态时,自动发送心跳包以确保连接处于活动状态。

• TCP_NODELAY:禁用Nagle算法,以减少网络延迟。

2.使用异步I/O

在Linux套接字编程中,可以使用非阻塞I/O或多路复用技术实现异步I/O。异步I/O可以提高应用程序的响应性和吞吐量。

3.优化套接字的缓冲区

在Linux套接字编程中,可以通过设置套接字缓冲区的大小和优化读写操作来提高网络应用程序的性能。

4.使用线程或进程池

在高流量环境中,使用多个线程或进程可以提高网络应用程序的性能,因为这样可以并发地处理来自客户端的请求。

5.编写健壮的错误处理代码

在网络编程中,错误很常见。为了确保程序的健壮性,开发人员应该编写健壮的错误处理代码,以正确地处理所有可能出现的错误情况并恢复失败的操作。

结论

Linux套接字编程是一种强大的网络编程技术,可以用于创建高效、健壮的网络应用程序。通过掌握Linux套接字编程的基本知识和技巧,开发人员可以更好地利用这一技术来实现他们的应用程序需求。本文提供的实用提示可以帮助读者更好地理解和运用Socket API,以创建更高效、更可靠的Linux网络应用程序。

相关问题拓展阅读:

Linux怎么使用ss命令查看系统的socket状态

ss是Socket Statistics的缩写。顾名思义,ss命令可以用来获取socket统计信息,它可以显示和netstat类似的内容。但ss的优势在于它能够显示更多更详细的有关TCP和连接状态的信息,而且比netstat更快速更高效。当服务器的socket连接数量变得非常大时,无论是使用netstat命令还是直接cat /proc/net/tcp,执行速度都会很慢。可能你不会有切身的感受,但请相信我,当服务器维持的连接达到上万个的时候,使用netstat等于浪费 生命,而用ss才是节省时间。天下武功唯快不破。ss快的秘诀在于,它利用到了TCP协议栈中tcp_diag。tcp_diag是一个用于分析统计的模块,可以获得Linux 内核中之一手的信息,这就确保了ss的快捷高效。当然,如果你的系统中没有tcp_diag,ss也可以正常运行,只裂烂是效率会变得稍慢。(但仍然比 netstat要快。)命令格式:  ss [参数]  ss [参数] [过滤].命令功能:  ss(Socket Statistics的肆念漏缩写)命令可以用来获取 socket统计信息,此命令输出的结果类似于 netstat输出的内容,但它能显示更多更详细的 TCP连接状态的信息,且比 netstat 更快速高效。它使用了 TCP协议栈中 tcp_diag(是一个用于分析统计的模块),能直接从获得之一手内核信息,这就使得 ss命令快捷高效。在没有 tcp_diag,ss也可以正常运行。   3.命令参数:  -h, –help 帮助信息  -V, –version 程序版本信息  -n, –numeric 不解析服务名称  -r, –resolve 解析主机名  -a, –all 显示所有套接字(sockets)  -l, –listening 显示监听状态的套接字(sockets)  -o, –options 显示计时器信息  -e, –extended 显示详细的套接字(sockets)信息  -m, –memory 显示套接字(socket)的内存使用情况  -p, –processes 显示使用套接字(socket)的进程  -i, –info 显示 TCP内部信息  -s, –summary 显示套接字(socket)使用概况  -4, –ipv4 仅显示IPv4的套接字(sockets)  -6, –ipv6 仅显示IPv6的套接字(sockets)  -0, –packet 显示高纤 PACKET 套接字(socket)  -t, –tcp 仅显示 TCP套接字(sockets)  -u, –udp 仅显示 UCP套接字(sockets)  -d, –dccp 仅显示 DCCP套接字(sockets)  -w, –raw 仅显示 RAW套接字(sockets)  -x, –unix 仅显示 Unix套接字(sockets)  -f, –family=FAMI 显示 FAMI类型的套接字(sockets),FAMI可选,支持 unix, inet, inet6, link, netlink  -A, –query=QUERY, –socket=QUERY  QUERY := {allinettcpudprawunixpacketnetlink}[,QUERY]  -D, –diag=FILE 将原始TCP套接字(sockets)信息转储到文件  -F, –filter=FILE 从文件中都去过滤器信息  FILTER := [ state TCP-STATE ] [ EXPRESSION ]  4.使用实例:  实例1:显示TCP连接  命令:ss -t -a  输出:  代码如下:  [root@localhost ~]# ss -t -a  State Recv-Q Send-Q Local Address:Port Peer Address:Port  LISTEN.0.0.1:ux *:*  LISTEN 0 0 *:3690 *:*  LISTEN 0 0 *:ssh *:*  ESTAB.168.120.204:ssh 10.2.0.68:[root@localhost ~]#  实例2:显示 Sockets 摘要  命令:ss -s  输出:   代码如下:  [root@localhost ~]# ss -s  Total: 34 (kernel 48)  TCP: 4 (estab 1, closed 0, orphaned 0, synrecv 0, timewait 0/0), ports 3《/p》 《p》Transport Total IP IPv6  *RAWUDPTCPINETFRAG[root@localhost ~]#  说明:列出当前的established, closed, orphaned and waiting TCP sockets  实例3:列出所有打开的网络连接端口  命令:ss -l  输出:  代码如下:  [root@localhost ~]# ss -l  Recv-Q Send-Q Local Address:Port Peer Address:Port.0.0.1:ux *:**:3690 *:**:ssh *:*  [root@localhost ~]#  实例4:查看进程使用的socket  命令:ss -pl  输出:  代码如下:  [root@localhost ~]# ss -pl  Recv-Q Send-Q Local Address:Port Peer Address:Port.0.0.1:ux *:* users:((“snmpd”,2716,8))*:3690 *:* users:((“svnserve”,3590,3))*:ssh *:* users:((“sshd”,2735,3))  [root@localhost ~]#  实例5:找出打开套接字/端口应用程序  命令:ss -lp grep输出:  代码如下:  [root@localhost ~]# ss -lpgrep*:1935 *:* users:((“fmsedge”,2913,18)).0.0.1:19350 *:* users:((“fmsedge”,2913,17))  [root@localhost ~]# ss -lpgrep*:3306 *:* users:((“mysqld”,2871,10))  [root@localhost ~]#  实例6:显示所有UDP Sockets  命令:ss -u -a  输出:  代码如下:  [root@localhost ~]# ss -u -a  State Recv-Q Send-Q Local Address:Port Peer Address:Port  UNCONN.0.0.1:syslog *:*  UNCONN 0 0 *:snmp *:*  ESTAB.168.120.203:.58.119.119:domain  [root@localhost ~]#  实例7:显示所有状态为established的TP连接  命令:ss -o state established ‘( dport = :tp or sport = :tp )’  输出:  代码如下:  [root@localhost ~]# ss -o state established ‘( dport = :tp or sport = :tp )’  Recv-Q Send-Q Local Address:Port Peer Address:Port  [root@localhost ~]#  实例8:显示所有状态为Established的HTTP连接  命令:ss -o state established ‘( dport = :http or sport = :http )’  输出:  代码如下:  [root@localhost ~]# ss -o state established ‘( dport = :http or sport = :http )’  Recv-Q Send-Q Local Address:Port Peer Address:Port.126.153.214:.168.10.42:http  [root@localhost ~]#   实例9:列举出处于 FIN-WAIT-1状态的源端口为 80或者 443,目标网络为 193.233.7/24所有 tcp套接字  命令:ss -o state fin-wait-1 ‘( sport = :http or sport = :https )’ dst 193.233.7/24  实例10:用TCP 状态过滤Sockets:  命令:  代码如下:  ss -4 state FILTER-NAME-HERE  ss -6 state FILTER-NAME-HERE  输出:  代码如下:  [root@localhost ~]#ss -4 state closing  Recv-Q Send-Q Local Address:Port Peer Address:Port.126.153.214:http 192.168.10.42:说明:  FILTER-NAME-HERE 可以代表以下任何一个:  代码如下:  established  syn-sent  syn-recv  fin-wait-1  fin-wait-2  time-wait  closed  close-wait  last-ack  listen  closing  all : 所有以上状态  connected : 除了listen and closed的所有状态  synchronized :所有已连接的状态除了syn-sent  bucket : 显示状态为maintained as minisockets,如:time-wait和syn-recv.  big : 和bucket相反。  实例11:匹配远程地址和端口号  命令:  代码如下:  ss dst ADDRESS_PATTERN  ss dst 192.168.1.5  ss dst 192.168.119.113:http  ss dst 192.168.119.113:tp  ss dst 192.168.119.113:443  输出:  代码如下:  [root@localhost ~]# ss dst 192.168.119.113  State Recv-Q Send-Q Local Address:Port Peer Address:Port  ESTAB.168.119.103:.168.119.113:ESTAB.168.119.103:.168.119.113:ESTAB.168.119.103:.168.119.113:ESTAB.168.119.103:.168.119.113:ESTAB.168.119.103:.168.119.113:ESTAB.168.119.103:.168.119.113:ESTAB.168.119.103:.168.119.113:ESTAB.168.119.103:.168.119.113:[root@localhost ~]# ss dst 192.168.119.113:http  State Recv-Q Send-Q Local Address:Port Peer Address:Port  [root@localhost ~]# ss dst 192.168.119.113:State Recv-Q Send-Q Local Address:Port Peer Address:Port  ESTAB.168.119.103:.168.119.113:[root@localhost ~]#  实例12:匹配本地地址和端口号  命令:  代码如下:  ss src ADDRESS_PATTERN  ss src 192.168.119.103  ss src 192.168.119.103:http  ss src 192.168.119.103:80  ss src 192.168.119.103:tp  ss src 192.168.119.103:25  输出:  代码如下:  [root@localhost ~]# ss src 192.168.119.103:State Recv-Q Send-Q Local Address:Port Peer Address:Port  ESTAB.168.119.103:.168.119.201:ESTAB.168.119.103:.168.119.201:ESTAB.168.119.103:.168.119.201:ESTAB.168.119.103:.168.119.201:ESTAB.168.119.103:.168.119.201:ESTAB.168.119.103:.168.119.201:ESTAB.168.119.103:.168.119.103:ESTAB.168.119.103:.168.119.201:ESTAB.168.119.103:.2.1.206:ESTAB.168.119.103:.2.1.206:ESTAB.168.119.103:.2.1.206:ESTAB.168.119.103:.2.1.206:ESTAB.168.119.103:.2.1.206:ESTAB.168.119.103:.2.1.206:ESTAB.168.119.103:.2.1.206:[root@localhost ~]#  实例13:将本地或者远程端口和一个数比较  命令:  代码如下:  ss dport OP PORT  ss sport OP PORT  输出:  代码如下:  [root@localhost ~]# ss sport = :http  [root@localhost ~]# ss dport = :http  [root@localhost ~]# ss dport \》 :[root@localhost ~]# ss sport \》 :[root@localhost ~]# ss sport \《 :[root@localhost ~]# ss sport eq :22  [root@localhost ~]# ss dport != :22  [root@localhost ~]# ss state connected sport = :http  [root@localhost ~]# ss \( sport = :http or sport = :https \)  [root@localhost ~]# ss -o state fin-wait-1 \( sport = :http or sport = :https \) dst 192.168.1/24  说明:  ss dport OP PORT 远程端口和一个数比较;ss sport OP PORT 本地端口和一个数比较。  OP 可以代表以下任意一个:  《= or le : 小于或等于端口号  》= or ge : 大于或等于端口号  == or eq : 等于端口号  != or ne : 不等于端口号  《 or gt : 小于端口号  》 or lt : 大于端口号  实例14:ss 和 netstat 效率对比  命令:  代码如下:  time netstat -at  time ss  输出:  代码如下:  [root@localhost ~]# time ss  real 0m0.739s  user 0m0.019s  sys 0m0.013s  [root@localhost ~]#  [root@localhost ~]# time netstat -at  real 2m45.907s  user 0m0.063s  sys 0m0.067s  [root@localhost ~]#  说明:  用time 命令分别获取通过netstat和ss命令获取程序和概要占用资源所使用的时间。在服务器连接数比较多的时候,netstat的效率完全没法和ss比。

Linux中 socket聊天室,给客户端发消息

//下面是一个实例

/**    

* socket.io chat    

*    

*/    

     

var web = require(‘QuickWeb’);    

     

// undefined    

var _ = undefined;     

     

/**    

 * 创建一个房间    

 *    

 * @param {string} room 房间名称    

 * @param {socket.io} io socket.io实例    

 */    

var Room = module.exports = function (room, io) {    

// 初始化socket.io实例,仅在之一次创建房间时需要设置io参数    

if (typeof io != ‘undefined’)    

Room.prototype.io = io;    

var io = this.io;    

   

// 房间成员列表    

var nicknames = this.nicknames = {};    

var onlinesum = this.onlinesum = 0;    

   

// 握手验证,如果是登录用户,则自动获取其昵称    

io.set(‘authorization’, function (handshakeData, callback) {    

// 通过客户端的cookie字符串来获取其session数据    

var sessionObject = handshakeData.sessionObject = web.session.getByCookie(handshakeData.headers.cookie);    

   

// 如果不是登录用户,则自动为其设置一个昵称    

var nickname = sessionObject.data.nickname;    

if (typeof nickname != ‘string’ || nickname == ”)    

nickname = ‘#’ + Math.floor(Math.random() * 1000) + ” + (new Date().getTime() %);    

sessionObject.data.nickname = 配带nickname;    

   

callback(null, true);    

});    

   

/** 连接处理 */    

var connectionHandle = function (socket) {    

onlinesum++;    

// 获取session    

var session = socket.handshake.sessionObject.data;    

var nickname = session.nickname;    

   

// 保持session,以免session过期    

var hold_session = socket.handshake.sessionObject.hold;    

   

/** 刷新在线列表 */    

refresh_online = function () {    

var n = 辩卖凳;    

for (var i in nicknames)    

n.push(i);    

socket.broadcast.emit(‘online list’, n);    

socket.emit(‘online list’, n);    

}    

   

// 新成员加入时,通知其他成员    

nicknames = socket;    

refresh_online();    

socket.broadcast.emit(‘system message’, nickname + ‘回来了,大家赶紧去喷他~~’);    

   

/** 公共消息 */    

socket.on(‘public message’, function (msg, cb) {    

hold_session();    

var timestamp = new Date().getTime();    

socket.broadcast.emit(‘public message’, nickname, msg, timestamp);    

cb();    

});    

   

/** 私人消息 */    

socket.on(‘private message’, function (to, msg, cb) {    

hold_session();    

var timestamp = new Date().getTime();    

var err = ”;    

for (var i in to) {    

var target = nicknames>;    

if (target) {    

cb();    

target.emit(‘private message’, nickname, msg, timestamp);   携旅 

}    

else {    

err += ‘“’ + to + ‘”不在线\n’;    

}    

}    

if (err != ”)    

cb(err);    

});    

   

/** 断开来连接 */    

socket.on(‘disconnect’, function () {    

delete nicknames;    

onlinesum–;    

socket.broadcast.emit(‘system message’, nickname + ‘悄悄地离开了。。。’);    

refresh_online();    

});    

   

/** 命令 */    

socket.on(‘command’, function (args, cb) {    

if (args.length 

#include// 包含套接字函数库

#include

#include// 包含AF_INET相关结构

#include// 包含AF_INET相关操作的函数

#include

#include

#include

#include

#include

#define PORT;

#define MYKEY

#define SIZE

int main()

{

int shmid;

char *shmaddr;//定义子进程共用的共享内存

shmid = shmget(MYKEY, SIZE, IPC_CREAT | 0600);

shmaddr= (char *) shmat(shmid, 0, 0);

if(shmid==-1)

{

printf(“shmid error\n”);

}

memset(shmaddr,0,SIZE);

int i=0;

char buf;

memset(buf,0,100);

int server_sockfd,client_sockfd;

int server_len,client_len;

struct sockaddr_in server_sockaddr,client_sockaddr;

server_sockfd = socket(AF_INET,SOCK_STREAM, 0); // 定义套接字类型

server_sockaddr.sin_family=AF_INET;

server_sockaddr.sin_port=PORT;

server_sockaddr.sin_addr.s_addr=INADDR_ANY;

server_len=sizeof(server_sockaddr);

//允许重复使用本地地址和套接字绑定

int j=1;

setsockopt(server_sockfd,SOL_SOCKET,SO_REUSEADDR,&j,sizeof(j));

//绑定端口

if(bind(server_sockfd,(struct sockaddr *)&server_sockaddr,server_len)==-1)

{

perror(“bind:”);

exit(1);

}

if(listen(server_sockfd,5)==-1)

{

perror(“listen:”);

exit(1);

}

printf(“Listening…\n”);

client_len=sizeof(client_sockaddr);

pid_t ppid,pid;

while(1)

{

if((client_sockfd=accept(server_sockfd,(struct sockaddr *)&client_sockaddr,&client_len))==-1)

{

perror(“accept error:”);

exit(1);

}

printf(“%s登录服务器\n”,inet_ntoa(client_sockaddr.sin_addr));

ppid=fork();

if(ppid==-1)

{

printf(“fork 1 failed:”);

}

if(ppid==0) //子进程用于接收客户端信息并发送

{

pid=fork();

if(pid==-1)

{

printf(“fork 2 failed:”);

exit(1);

}

int recvbytes;

if(pid==0)//子子进程用于接收消息

{

while(1)

{

if((recvbytes=recv(client_sockfd,buf,100,0))==-1)

{

perror(“read client_sockfd failed:”);

}

// printf(“recvbytes=%d\n”,recvbytes);

usleep(10000);

printf(“client send buf=%s\n”,buf);

for(i=0;i0) //子进程用于发送消息

{

while(1)

{

if(*(shmaddr+i*100)!=0)

{

// strcpy(&buf,shmaddr+100*i);

// buf++;

write(client_sockfd,shmaddr,SIZE);

// send(client_sockfd,buf,strlen(buf),0);

// printf(“the server is send buf=%c”,buf);

// printf(“send client :%s\n”,(shmaddr+i*100)) ;

i++;

}

}

}

}

if(ppid>0)//总父进程返回等待接收消息

{

close(client_sockfd);

}

}

}

客户端:client.c

#include

#include// 包含套接字函数库

#include

#include// 包含AF_INET相关结构

#include// 包含AF_INET相关操作的函数

#include

#include

#include

#define PORT 8888

#define IP_ADDR “192.168.110.185”

#define SIZE 10240

int main()

{

struct tm *timeptr;

time_t timeval;

char tm;

//(void)time(&timeval);

//printf(“the date is %s\n”,ctime(&timeval));

// printf(“The time is %s\n”,tm);

int sockfd; // 用于保存客户套接字标识符

int len;// 用于客户消息长度

struct sockaddr_in address; // 定义客户套接字地址

int result;

sockfd = socket(AF_INET,SOCK_STREAM, 0); // 定义套接字类型

address.sin_family = AF_INET; // 定义套接字地址中的域

address.sin_addr.s_addr = inet_addr(IP_ADDR);// 定义套接字地址

address.sin_port = htons(PORT); // 定义套接字端口

char buf; // 定义要传送的消息

memset(buf,0,100);

char str;//存贮输入的语句

char shmaddr; //接受服务器发送的全部聊天数据

int i=0;

char myname;

char say={“说:”};

printf(“欢迎来到聊天室,请输入你的姓名:\n”);

scanf(“%s”,myname);

len = sizeof(address);

result = connect(sockfd, (struct sockaddr *) &address, len); // 请求连接

if (result == -1)

{

perror(“Connect failed”);

return 1;

}

printf(“%s成功登录服务器:\n”,myname);

pid_t pid;

pid=fork();

if(pid==-1)

{

printf(“fork failed”);

}

int sendbytes=0;

if(pid==0)//子进程用于发送数据

{

while(1)

{

printf(“请输入语句:\n”);

scanf(“%s”,str);

(void)time(&timeval);

strcpy(tm,ctime(&timeval));

strcpy(buf,myname);//姓名传入buf中

strcat(buf,tm); //时间传入buf中

strcat(buf,say);

strcat(buf,str); //语句传入bufz中

//read(0,buf,strlen(buf));

// send(sockfd,buf,strlen(buf),0);

// getchar();

if((sendbytes=write(sockfd, buf, 100))==-1)

{

perror(“send to server failed:”);

} // 向服务器传送消息

// printf(“sendbytes=%d\n”,sendbytes);

// printf(“buf=%s\n”,buf);

// printf(“input buf=%s\n”,buf);

usleep(1000);

memset(buf,0,100);

memset(tm,0,50);

}

}

if(pid>0) //父进程用于接受消息并读取

{

while(1)

{

read(sockfd,shmaddr,SIZE);

// printf(“server send shmaddr=%s\n”,shmaddr);

if(*(shmaddr+i*100)!=0)

{

printf(“%s\n”,(shmaddr+i*100)) ;

i++;

}

usleep(1000);

}

}

close(sockfd);

return 0;

}

这题目液搜是Linux Socket 很普遍的练习

你没贴代码,不知道问题在哪?

请试试下腊简面 Server.c and Client.c

服务器:server.c

#include

#include// 包含套接字函数库

#include

#include// 包含AF_INET相关结构

#include// 包含AF_INET相关操作的函数

#include

#include

#include

#include

#include

#define PORT;

#define MYKEY

#define SIZE

int main()

{

int shmid;

char *shmaddr;//定义子进程共用的共享内存

shmid = shmget(MYKEY, SIZE, IPC_CREAT | 0600);

shmaddr= (char *) shmat(shmid, 0, 0);

if(shmid==-1)

{

printf(“shmid error\n”);

}

memset(shmaddr,0,SIZE);

int i=0;

char buf;

memset(buf,0,100);

int server_sockfd,client_sockfd;

int server_len,client_len;

struct sockaddr_in server_sockaddr,client_sockaddr;

server_sockfd = socket(AF_INET,SOCK_STREAM, 0); // 定义套接字类型

server_sockaddr.sin_family=AF_INET;

server_sockaddr.sin_port=PORT;

server_sockaddr.sin_addr.s_addr=INADDR_ANY;

server_len=sizeof(server_sockaddr);

//允许重复使用本地地址和套接字绑定

int j=1;

setsockopt(server_sockfd,SOL_SOCKET,SO_REUSEADDR,&j,sizeof(j));

//绑定端口

if(bind(server_sockfd,(struct sockaddr *)&server_sockaddr,server_len)==-1)

{

perror(“bind:”);

exit(1);

}

if(listen(server_sockfd,5)==-1)

{

perror(“listen:”);

exit(1);

}

printf(“Listening…\n”);

client_len=sizeof(client_sockaddr);

pid_t ppid,pid;

while(1)

{

if((client_sockfd=accept(server_sockfd,(struct sockaddr *)&client_sockaddr,&client_len))==-1)

{

perror(“accept error:”);

exit(1);

}

printf(“%s登录服务器\n”,inet_ntoa(client_sockaddr.sin_addr));

ppid=fork();

if(ppid==-1)

{

printf(“fork 1 failed:”);

}

if(ppid==0) //子进程用于接收客户端信息并发送

{

pid=fork();

if(pid==-1)

{

printf(“fork 2 failed:”);

exit(1);

}

int recvbytes;

if(pid==0)//子子进程用于接收消息

{

while(1)

{

if((recvbytes=recv(client_sockfd,buf,100,0))==-1)

{

perror(“read client_sockfd failed:”);

}

// printf(“recvbytes=%d\n”,recvbytes);

usleep(10000);

printf(“client send buf=%s\n”,buf);

for(i=0;i0) //子进程用于发送消息

{

while(1)

{

if(*(shmaddr+i*100)!=0)

{

// strcpy(&buf,shmaddr+100*i);

// buf++;

write(client_sockfd,shmaddr,SIZE);

// send(client_sockfd,buf,strlen(buf),0);

// printf(“the server is send buf=%c”,buf);

// printf(“send client :%s\n”,(shmaddr+i*100)) ;

i++;

}

}

}

}

if(ppid>0)//总父进程返回等待接收消息

{

close(client_sockfd);

}

}

}

客户端:client.c

#include

#include// 包含套接字函数库

#include

#include// 包含AF_INET相关结构

#include// 包含AF_INET相关操作的函数

#include

#include

#include

#define PORT 8888

#define IP_ADDR “192.168.110.185”

#define SIZE 10240

int main()

{

struct tm *timeptr;

time_t timeval;

char tm;

//(void)time(&timeval);

//printf(“the date is %s\n”,ctime(&timeval));

// printf(“The time is %s\n”,tm);

int sockfd; // 用于保存客户套接字标识符

int len;// 用于客户消息长度

struct sockaddr_in address; // 定义客户套接字地址

int result;

sockfd = socket(AF_INET,SOCK_STREAM, 0); // 定义套接字类型

address.sin_family = AF_INET; // 定义套接字地址中的域

address.sin_addr.s_addr = inet_addr(IP_ADDR);// 定义套接字地址

address.sin_port = htons(PORT); // 定义套接字端口

char buf; // 定义要传送的消息

memset(buf,0,100);

char str;//存贮输入的语句

char shmaddr; //接受服务器发送的全部聊天数据

int i=0;

char myname;

char say={“说:”};

printf(“欢迎来到聊天室,请输入你的姓名:\n”);

scanf(“%s”,myname);

len = sizeof(address);

result = connect(sockfd, (struct sockaddr *) &address, len); // 请求连接

if (result == -1)

{

perror(“Connect failed”);

return 1;

}

printf(“%s成功登录服务器:\n”,myname);

pid_t pid;

pid=fork();

if(pid==-1)

{

printf(“fork failed”);

}

int sendbytes=0;

if(pid==0)//子进程用于发送数据

{

while(1)

{

printf(“请输入语句:\n”);

scanf(“%s”,str);

(void)time(&timeval);

strcpy(tm,ctime(&timeval));

strcpy(buf,myname);//姓名传入buf中

strcat(buf,tm); //时间传入buf中

strcat(buf,say);

strcat(buf,str); //语句传入bufz中

//read(0,buf,strlen(buf));

// send(sockfd,buf,strlen(buf),0);

// getchar();

if((sendbytes=write(sockfd, buf, 100))==-1)

{

perror(“send to server failed:”);

} // 向服务器传送消息

// printf(“sendbytes=%d\n”,sendbytes);

// printf(“buf=%s\n”,buf);

// printf(“input buf=%s\n”,buf);

usleep(1000);

memset(buf,0,100);

memset(tm,0,50);

}

}

if(pid>0) //父进程用于接受消息并读取

{

while(1)

{

read(sockfd,shmaddr,SIZE);

// printf(“server send shmaddr=%s\n”,shmaddr);

if(*(shmaddr+i*100)!=0)

{

printf(“%s\n”,(shmaddr+i*100)) ;

i++;

}

usleep(1000);

}

}

close(sockfd);

return 0;

关于linux socket 使用的介绍到此就结束了,不知道你从中找到你需要的信息了吗 ?如果你还想了解更多这方面的信息,记得收藏关注本站。


数据运维技术 » Linux套接字编程指南:掌握Socket使用技巧 (linux socket 使用)