#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <errno.h>
#include <ctype.h>
#define SERV_PORT 7000
//running command: "./server_tcp -p 7001"
int main(int argc, char** argv)
{
int opt
int port = SERV_PORT
while((opt = getopt(argc, argv, "p:")) != -1){
switch (opt){
case 'p': port = atoi(optarg)
break
default: break
}
}
struct sockaddr_in serv_addr, clnt_addr
socklen_t clnt_len
int lfd, cfd
int n, i
char buf[BUFSIZ]
lfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)
if(lfd <0){
printf("%s\n", "socket error")
exit(1)
}
serv_addr.sin_family = AF_INET
serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1")
serv_addr.sin_port = htons(port)
bind(lfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr))
listen(lfd, 128)
clnt_len = sizeof(serv_addr)
cfd = accept(lfd, (struct sockaddr*)&clnt_addr, &clnt_len)
if(cfd == -1){
printf("accept error\n")
if(errno == EAGAIN || errno == EWOULDBLOCK){
printf("normal error")
}else{
printf("innormal error\n")
return -1
}
}
while(1){
n = read(cfd, buf, BUFSIZ)
if(n >0){
printf("receive centent: %s\n", buf)
for(i = 0i <ni++){
buf[i] = toupper(buf[i])
}
}
write(cfd, buf, n)
}
close(cfd)
close(lfd)
return 0
}
客户端可以省略,使用nc命令可以模拟客户端连接: nc 127.1 7001
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <string.h>
int main()
{
struct sockaddr_in serv_addr
int lfd
lfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)
serv_addr.sin_family = AF_INET
serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1")//服务器和客户端IP相同
serv_addr.sin_port = htons(6666)
connect(lfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr))
write(lfd, "hello socket", strlen("hello socket"))
char rbuf[BUFSIZ]
read(lfd, rbuf, BUFSIZ)
printf("rbuf=%s\n", rbuf)
close(lfd)
return 0
}
首先需要在电脑上搭建服务器,关于网上好多按步骤安装apache,sql,phpmyadmin的方法复杂而且没有必要,这里推荐wamp这样的一个集成软件,安装非常简单,一路点击next,apache+sql+phpmyadmin的环境一键搭好。在百度中搜索Wamp下载,直接下载就行。下载完wamp进行安装,一路点击next,装在c:\wamp下,最后install完成.在浏览器输入localhost,出现以下页面说明安装成功了。现在服务器和php环境算是搭好了。此时在桌面右下角任务栏中会有wamp的图标,点击会有下图显示,www是网站页面根目录,localhost是网站默认主页,点击phpmyadmin可以进入数据库管理界面.现在网站只能在PC上显示,如何能把网站放到互联网上让朋友也欣赏一下。这时就需要一款叫花生壳的软件,提供动态的域名映射.下载网址如下:http://hsk.oray.com/download/#type=windows|lan下载完软件按步骤安装即可,这时候需要注册一下花生壳会员,注册时按网页提示的步骤即可,用身份证注册可以获得一个免费域名。用注册的账号密码登陆软件。会出现以下界面。这里的网址是申请的免费域名。在域名上右键,选择新花生壳管理,填写应用名称,这个可以随便填,内网主机为本机内网的ip地址,这时需要查看以下,win+R在cmd中输入,ipconfig/all,可以看到ipv4地址,填写即可。端口为80端口。同时,现在需要设置一下路由器。在浏览器输入192.168.1.1。输入路由器用户名和密码,一般都为admin。进入路由器界面。需要设置三个地方,首先是动态DNS,选择服务商为花生壳,填写用户名密码,验证保存。然后是转发规则中的虚拟服务器,添加新条目,端口80,ip地址为内网ip。最后是,DMZ主机,设置开启,ip为内网本机ip。现在设置基本完成,这时就可以测试了。注意,要把防火墙关闭,否则外网还是访问不了本机的网站。在控制面板中把防火墙关闭。现在可以写一段html代码,命名为index.html(注意此时先把index.php放到别的文件夹)放入wamp\www目录中,来测试访问。最后,在浏览器输入花生壳域名,看看是不是就能访问了。同时也可以把自域名发送给朋友,让他们帮测试一下。用C#实现多线程TCP协议的服务器端程序:// <summary>
/// Tcp客户线程类(服务端),ThreadServerProcessor 线程产生的客户连接,用该线程读写
/// </summary>
public class ThreadClientProcessor
{
//Tcp连接实例
private TcpClient tcpClient
//消息框,本来想写日志用
private System.Windows.Forms.ListBox MessageList
private string Password//该连接登陆密码
private string Cmd1Echo
private string Cmd2Echo
private bool ClientLogOn//客户是否登陆
private bool TcpClose
public ThreadClientProcessor(){}
//构造函数,参数解释:Tcp客户,消息框,该服务密码(password命令后的参数) ,命令回应串 1,2 ******************
public ThreadClientProcessor(TcpClient client , ListBox listBox,string LogonText ,string cmd1echo,string cmd2echo)
{
ClientList.Add(this) //把当前实例加入一个列表中,方便以后控制
this.tcpClient=client
this.MessageList=listBox
this.Password=LogonText
this.Cmd1Echo=cmd1echo
this.Cmd2Echo=cmd2echo
this.ClientLogOn=false
this.TcpClose=false
}
public static char[] CmdSplit={' '}//读来的串由' ' 进行分离,命名+' '+参数
//public const string[] Cmd=new string[] { "password","cmd1","cmd2","echo","bye"}
//该函数由你自己写,这个只是给一个例子,
//功能:命令处理器,给个命令串,返回该命令处理结果,把命令和处理结果放在一个文本文件里,便于系统升级
public string TcpCmd(string s)
{
string result
try
{
string cmdarg=s.Trim()
string[] args=cmdarg.Split(CmdSplit)
string cmd=args[0].ToLower()
switch (cmd )
{
case "password" :
if (args.Length>1)
{
ClientLogOn= Password.Equals(args[1].Trim())
result=ClientLogOn? "登陆成功":"密码不正确,未登陆"
}
else result= "登陆时候,没有输入密码"
break
case "cmd1":
result=ClientLogOn?this.Cmd1Echo:"该命令无权执行,请先登陆"
break
case "cmd2":
result=ClientLogOn?this.Cmd2Echo:"该命令无权执行,请先登陆"
break
case "echo":
result=string.Format("服务器回应:\n {0}",s)
break
case "bye":
this.TcpClose=true
result="DisConnected"
break
default:
result="不可识别的命令"
break
}
}
catch
{
result="解析命令发生错误,你输入的是狗屁命令,TMD *^* "
}
return result
} //end cmd
//定义一个线程,该线程对应的函数是 void start()(不是Start())********************************
//一下程序主要是操作该线程
public System.Threading.Thread tcpClientThread
//启动客户连接线程 *************************************************************
public void Start()
{
tcpClientThread=new Thread(new ThreadStart(start))
tcpClientThread.Priority=ThreadPriority.BelowNormal
tcpClientThread.Start()
}
//断开该当前实例连接,终止线程 **************************************************************
public void Abort()
{
if (this.tcpClientThread!=null)
{
//tcpClientThread.Interrupt()
tcpClientThread.Abort()
//一定要等一会儿,以为后边tcpClient.Close()时候,会影响NetWorkStream的操作
Thread.Sleep(TimeSpan.FromMilliseconds(100))
tcpClient.Close()
}
}
//静态列表,包含了每个连接实例(在构造实例时候使用了 ArrayList.Add( object))
private static System.Collections.ArrayList ClientList=new ArrayList()
//断开所有的Tcp客户连接,静态方法*************************************************************
public static void AbortAllClient()
{
for(int j=0 j<ClientList.Countj++)
{
//从实例列表中取一个对象,转化为ThreadClientProcessor对象
ThreadClientProcessor o=(ThreadClientProcessor ) ClientList[j]
//调用ThreadClientProcessor 对象的停止方法
o.Abort()
}
//清除连接列表
ClientList.Clear()
}
//读写连接的函数,用于线程//*******************************************************************
private void start()
{
byte[] buf=new byte[1024*1024]//预先定义1MB的缓冲
int Len=0//流的实际长度
NetworkStream networkStream=tcpClient.GetStream()//建立读写Tcp的流
try
{
byte[] p=Encoding.UTF8.GetBytes(" 欢迎光临,请输入密码" )
//向Tcp连接写 欢迎消息
if (!this.ClientLogOn )
networkStream.Write(p,0,p.Length)
//开始循环读写tcp流
while (!TcpClose)
{
//如果当前线程是在其它状态,(等待挂起,等待终止.....)就结束该循环
if (Thread.CurrentThread.ThreadState!=ThreadState.Running)
break
//判断Tcp流是否有可读的东西
if ( networkStream.DataAvailable)
{
//从流中读取缓冲字节数组
Len=networkStream.Read(buf,0,buf.Length)
//转化缓冲数组为串
string cmd=Encoding.UTF8.GetString(buf,0,Len)
this.MessageList.Items.Add("客户机:"+cmd)
//处理该缓冲的串(分析命令),分析结果为res串
string res=TcpCmd(cmd)
//把命令的返回结果res 转化为字节数组
byte[] result=Encoding.UTF8.GetBytes(res)
//发送结果缓冲数组给客户端
networkStream.Write(result,0,result.Length)
this.MessageList.Items.Add("服务器回应:"+res)
}
else
{
//Thread.Sleep(TimeSpan.FromMilliseconds(200d))
//this.MessageList.Items.Add("客户机无命令")
//如果当前Tcp连接空闲,客户端没有写入,则当前线程停止200毫秒
Thread.Sleep(TimeSpan.FromMilliseconds(200d))
}
}
欢迎分享,转载请注明来源:夏雨云
评论列表(0条)